最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • svg编辑器——新建路径

    正文概述 掘金(从零开始的程序媛)   2021-02-22   661

    演示地址

    adjlyadv.github.io/svg-editor/

    拖拽锚点的问题

    使用mousedown、mouseup、mousemove来实现锚点的拖拽功能,这里需要注意的是要把mousemove事件绑定在父元素上。

    如果绑定在需要移动的元素上,鼠标移动过快的时候就会移出元素的范围,造成元素的停滞。

    在项目中使用了mobx作为全局状态管理,而且会有多个需要拖动的锚点,所以在store中设置了一个dragging对象,来记录当前鼠标点击的是属于哪个path上的哪个node。

    示例代码

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>测试</title>
        <style>
            #container{
                margin-top:100px;
                margin-left:200px;
            }
            svg{
                width:400px;
                height:400px;
                background-color: black;
            }
            circle{
                cx:10;
                cy:10;
                fill: #0FF;
                stroke: #55f;
                r: 10;
            }
        </style>
    </head>
    <body>
        <div id="container">
            <svg id="bg" width="400" height="400">
                <circle id="ci"/>
            </svg>
        </div>
    
        <script>
            let container = document.getElementById('container')
            let svg = document.getElementById('bg');
            let circle = document.getElementById('ci');
            let dragged = false;
    
            circle.onmousedown = (event) =>{
                dragged = true;
                console.log('down');
            }
    
            circle.onmouseup = (event) =>{
                dragged = false;
                console.log('up');
            }
            svg.onmousemove = (event) =>{
                if(dragged){
                    let x = event.clientX 
                    let y = event.clientY
                    circle.style.cx = x - container.offsetLeft;
                    circle.style.cy = y - container.offsetTop;
                }
            }
    
        </script>
    </body>
    </html>
    

    新建路径时的渲染

    通过观察PS的钢笔工具以及其他类似产品,总结新建路径的流程如图 svg编辑器——新建路径 svg编辑器——新建路径

    渲染

    在选择控制点的时候(鼠标按下移动的过程)需要渲染锚点和鼠标连线的直线。

    <circle className="point-control" cx={newNode.posX} cy={newNode.posY} stroke="#55f" r="10" />
    <line x1={newNode.posX} y1={newNode.posY} x2={newNode.ctrPosX} y2={newNode.ctrPosY} stroke="#555" strokeWidth={width} />
    <circle className="point-control" cx={newNode.ctrPosX} cy={newNode.ctrPosY} stroke="#000" r="10" />
    

    在选择新的锚点的时候(鼠标起来之后移动的过程),需要渲染鼠标和上一个锚点的path。

    let getD = `M ${lastNode.posX} ${lastNode.posY} C ${mockCtrX} ${mockCtrY} ${newNode.ctrPosX} ${newNode.ctrPosY}`;
    
    if(lastNode.posX !== newNode.posX && lastNode.posY !== newNode.posY){
       getD += ` ${newNode.posX} ${newNode.posY}`;
    }else{
       getD += ` ${newNode.ctrPosX} ${newNode.ctrPosY}`;//当没有确定新的锚点时
    }
    
    <path d = {getD}  fill="none" stroke="#000" strokeWidth="1"/>
    

    判断起点

    在path中起点只有一个控制点,所以当起点为lastnode的时候需要改变一下控制点。使用了一个startnode的变量来判断是否是路径上的初始点。

                  if(startNode){// 处理第一个节点的渲染
                    setLastnode({
                      ...newNode,
                      ctrPosX: mockCtrX,
                      ctrPosY: mockCtrY
                    })
                    setStartNode(false);
                  }else{//是其他节点
                    setLastnode({
                      ...newNode
                    })
                  }
    

    区分双击事件和mousedown mouseup

    在鼠标事件中的顺序是 mousedown mouseup click mousedown mouseup click doubleclick所以如果是双击事件就会触发两次mouseup,为了区分mouseup和doubleclick,在mouseup上加了一个定时器,然后在doublecklick处清除定时器,这样就可以在双击时完成路径最后一个锚点的添加。

    const handleMouseUp = (event: any) => {
        event.stopPropagation();
        clearTimeout(mouseUpTimeChange);
        mouseUpTimeChange = setTimeout(()=>{},250);
    }
      const pathDoubleClick:any = () => {
        clearTimeout(mouseUpTimeChange);
        ...
      }
    

    起源地下载网 » svg编辑器——新建路径

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元