演示地址
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的钢笔工具以及其他类似产品,总结新建路径的流程如图
渲染
在选择控制点的时候(鼠标按下移动的过程)需要渲染锚点和鼠标连线的直线。
<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);
...
}
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!