npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

d8d-design-transform

v1.0.44

Published

D8D Design Transform is a powerful React component library designed for creating scalable and pannable canvases. It supports features such as dragging, resizing, and nesting of items. This library is highly suitable for building complex design tools, char

Downloads

20

Readme

D8D Design Transform

D8D Design Transform 是一个功能强大的React组件库,用于创建可缩放、可平移的画布,并支持拖拽、调整大小和嵌套的项目。这个库非常适合用于构建复杂的设计工具、图表编辑器或任何需要灵活交互的可视化应用。

目录

  1. 功能特点
  2. 安装
  3. 基本使用示例
  4. 高级使用示例
  5. 主要组件
  6. 项目结构
  7. 高级用法
  8. 性能优化
  9. 注意事项
  10. 贡献
  11. 许可证
  12. 联系方式

功能特点

  • 可缩放和平移的画布: 用户可以自由缩放和移动整个画布视图。
  • 绘制模式: 支持在画布上直接绘制新的矩形项目。
  • 框选模式: 允许用户通过拖动鼠标选择多个项目。
  • 项目操作:
    • 拖拽: 可以自由移动画布上的项目。
    • 调整大小: 支持通过拖动边缘或角落来调整项目尺寸。
    • 嵌套: 项目可以作为容器,包含其他项目。
  • 自动适应屏幕: 画布会自动调整以适应不同的屏幕尺寸。
  • 复制、粘贴、剪切和删除: 支持基本的编辑操作(目前仅打印日志)。
  • 自定义右键菜单: 可以为项目添加自定义的右键菜单选项(目前仅打印日志)。
  • 高度可定制: 使用Tailwind CSS,可以轻松自定义组件样式。

安装

使用npm安装:

npm install d8d-design-transform d8d-design-canvas

基本使用示例

以下是一个基本的使用示例:

import React, { useRef, useState, useLayoutEffect } from 'react';
import { Canvas, type CanvasRef } from "d8d-design-canvas";
import { TransformLayer, ItemsContainer } from "d8d-design-transform";
import "d8d-design-canvas/dist/style.css";
import "d8d-design-transform/dist/style.css";

function App() {
  const canvasRef = useRef<CanvasRef>(null);
  const [drawMode, setDrawMode] = useState(false);
  const [selectMode, setSelectMode] = useState(false);
  const [scale, setScale] = useState(1);
  const [items, setItems] = useState<Item[]>(initialItems);
  const [selectedItems, setSelectedItems] = useState<Set<string>>(new Set());

  useLayoutEffect(() => {
    if (canvasRef.current) {
      setTimeout(() => {
        canvasRef.current?.fitToScreen("transform-layer");
      }, 1000);
    }
  }, []);

  const handleDrawComplete = (rect: { x: number; y: number; width: number; height: number }) => {
    const newItem: Item = {
      id: Date.now().toString(),
      x: rect.x,
      y: rect.y,
      width: rect.width,
      height: rect.height,
      containerId: null,
      className: `bg-${getRandomColor()}-500`,
    };
    setItems((prevItems) => [...prevItems, newItem]);
    setDrawMode(false);
  };

  const handleSelectComplete = (rect: { x: number; y: number; width: number; height: number }) => {
    const selectedIds = items.filter(item => 
      item.x < rect.x + rect.width &&
      item.x + item.width > rect.x &&
      item.y < rect.y + rect.height &&
      item.y + item.height > rect.y
    ).map(item => item.id);
  
    setSelectedItems(new Set(selectedIds));
  };

  return (
    <div className="app-container">
      <Canvas
        ref={canvasRef}
        controlledScale={scale}
        onScaleChange={setScale}
        drawMode={drawMode}
        selectMode={selectMode}
        onDrawComplete={handleDrawComplete}
        onSelectComplete={handleSelectComplete}
      >
        <ItemsContainer items={items} />
        <TransformLayer
          items={items}
          onItemsChange={setItems}
          selectedItems={selectedItems}
          onSelectedItemsChange={setSelectedItems}
        />
      </Canvas>
    </div>
  );
}

export default App;

高级使用示例

以下是一个包含编辑功能和容器回调的高级使用示例:

import React, { useRef, useState, useLayoutEffect } from 'react';
import { Canvas, type CanvasRef } from "d8d-design-canvas";
import { TransformLayer, ItemsContainer, TransformLayerRef, TTransformItem, EditableDiv } from "d8d-design-transform";
import "d8d-design-canvas/dist/style.css";
import "d8d-design-transform/dist/style.css";

function App() {
  const canvasRef = useRef<CanvasRef>(null);
  const [drawMode, setDrawMode] = useState(false);
  const [selectMode, setSelectMode] = useState(false);
  const [scale, setScale] = useState(1);
  const [items, setItems] = useState<Item[]>(initialItems);
  const [selectedItems, setSelectedItems] = useState<Set<string>>(new Set());

  useLayoutEffect(() => {
    if (canvasRef.current) {
      setTimeout(() => {
        canvasRef.current?.fitToScreen("transform-layer");
      }, 1000);
    }
  }, []);

  const handleDrawComplete = (rect: { x: number; y: number; width: number; height: number }) => {
    const newItem: Item = {
      id: Date.now().toString(),
      x: rect.x,
      y: rect.y,
      width: rect.width,
      height: rect.height,
      containerId: null,
      className: `bg-${getRandomColor()}-500`,
    };
    setItems((prevItems) => [...prevItems, newItem]);
    setDrawMode(false);
  };

  const handleSelectComplete = (rect: { x: number; y: number; width: number; height: number }) => {
    const selectedIds = items.filter(item => 
      item.x < rect.x + rect.width &&
      item.x + item.width > rect.x &&
      item.y < rect.y + rect.height &&
      item.y + item.height > rect.y
    ).map(item => item.id);
  
    setSelectedItems(new Set(selectedIds));
  };

  const handleEnterContainer = (id: string, containerId: string) => {
    console.log(`项目 ${id} 进入容器 ${containerId}`);
    // 在这里执行进入容器时的逻辑
  };

  const handleLeaveContainer = (id: string) => {
    console.log(`项目 ${id} 离开其容器`);
    // 在这里执行离开容器时的逻辑
  };

  return (
    <div className="app-container">
      <Canvas
        ref={canvasRef}
        controlledScale={scale}
        onScaleChange={setScale}
        drawMode={drawMode}
        selectMode={selectMode}
        onDrawComplete={handleDrawComplete}
        onSelectComplete={handleSelectComplete}
      >
        <ItemsContainer items={items} />
        <TransformLayer
          items={items}
          onItemsChange={setItems}
          selectedItems={selectedItems}
          onSelectedItemsChange={setSelectedItems}
          onEnterContainer={handleEnterContainer}
          onLeaveContainer={handleLeaveContainer}
        />
      </Canvas>
    </div>
  );
}

export default App;

主要组件

Canvas

Canvas 组件是整个画布的基础,提供了缩放、平移、绘制和选择的功能。

主要属性:

  • controlledScale: 控制画布的缩放比例
  • onScaleChange: 缩放比例变化时的回调函数
  • drawMode: 是否启用绘制模式
  • selectMode: 是否启用框选模式
  • onDrawComplete: 绘制完成时的回调函数
  • onSelectComplete: 框选完成时的回调函数

TransformLayer

TransformLayer 组件处理项目的拖拽、调整大小等交互操作。

主要属性:

  • items: 画布上的所有项目数组
  • onItemsChange: 项目发生变化时的回调函数
  • selectedItems: 当前选中的项目ID集合
  • onSelectedItemsChange: 选中项目发生变化时的回调函数
  • onEnterContainer: 项目进入容器时的回调函数
  • onLeaveContainer: 项目离开容器时的回调函数

ItemsContainer

ItemsContainer 组件负责渲染画布上的所有项目。

主要属性:

  • items: 要渲染的项目数组

项目结构

项目的基本结构如下:

interface Item {
  id: string;
  x: number;
  y: number;
  width: number;
  height: number;
  containerId: string | null;
  className: string;
}

高级用法

  1. 自定义项目样式: 通过修改className属性,可以为每个项目应用不同的Tailwind CSS类。

  2. 嵌套项目: 通过设置containerId,可以创建项目的父子关系,实现嵌套效果。

  3. 自定义操作: 可以通过扩展TransformLayer组件来添加自定义的项目操作,如旋转、翻转等。

  4. 动态自定义属性: 使用回调函数为每个项目动态设置自定义类名和样式。

    例如:

    const getCustomProps = (item) => {
      if (item.id === 'item1') {
        return {
          className: 'my-custom-class-1',
          style: { backgroundColor: 'red' }
        };
      }
      if (item.id === 'item2') {
        return {
          className: 'my-custom-class-2',
          style: { border: '2px solid blue' }
        };
      }
      return {};
    };
    
    return (
      <TransformLayer
        // ... 其他属性 ...
        getCustomProps={getCustomProps}
      />
    );

    这允许您根据项目的属性、状态或任何其他条件动态地为每个 TransformItem 指定自定义类名和样式。

  5. 自定义项目菜单: 使用renderMenu属性为每个项目添加自定义的顶部菜单。

    例如:

    const renderMenu = (id) => (
      <div>
        <button onClick={() => console.log(`编辑 ${id}`)}>编辑</button>
        <button onClick={() => console.log(`删除 ${id}`)}>删除</button>
      </div>
    );
    
    return (
      <TransformLayer
        // ... 其他属性 ...
        renderMenu={renderMenu}
      />
    );

    这将在每个项目的顶部显示一个包含"编辑"和"删除"按钮的菜单。您可以根据需要自定义菜单的内容和样式。如果不提供renderMenu属性,则不会显示菜单。

  6. 容器回调: 使用 onEnterContaineronLeaveContainer 回调来监听项目进入或离开容器的事件。

    例如:

    const handleEnterContainer = (id, containerId) => {
      console.log(`项目 ${id} 进入容器 ${containerId}`);
      // 执行进入容器时的逻辑
    };
    
    const handleLeaveContainer = (id) => {
      console.log(`项目 ${id} 离开其容器`);
      // 执行离开容器时的逻辑
    };
    
    return (
      <TransformLayer
        // ... 其他属性 ...
        onEnterContainer={handleEnterContainer}
        onLeaveContainer={handleLeaveContainer}
      />
    );

    这允许您在项目进入或离开容器时执行自定义逻辑,例如更新状态、触发动画或发送网络请求等。

性能优化

对于大量项目的场景,考虑使用虚拟化技术来优化渲染性能。可以结合使用react-windowreact-virtualized等库。

注意事项

  • 确保正确导入了所有必要的样式文件。
  • 推荐使用Tailwind CSS来自定义组件样式,以保持一致性和灵活性。
  • 在处理大量项目时,注意性能优化,考虑使用虚拟化或分页加载技术。
  • 使用renderMenu属性时,请确保返回的React节点不会过于复杂,以避免性能问题。

贡献

欢迎提交问题和拉取请求。对于重大更改,请先开issue讨论您想要更改的内容。

许可证

MIT

联系方式

如有任何问题或建议,请联系我们: [email protected]

访问我们的网站了解更多信息: https://d8d.fun