这段时间比较忙,php的设计模式想写工厂模式,但是比较难写,不是一时半会儿能写完的,先把现在正在使用的关于svg中元素的拖动,记录一下。
借助svg,我们可以画出多种多样的图形,而且利用g标签,还可以把多个标签组合在一起,让他们具有相同的行为。语法也比较简洁,希望还么有接触过的同学,学习一下。
要实现拖动功能(大神绕行…),我们需要给元素定义mousedown(响应鼠标在元素范围按住),mousemove(移动),mouseup(松开鼠标),先定义一个rect标签(有机会补图)。
<rect width="100" height="100" fill='#f00' stroke='#d7a7bd' stroke-width='3' stroke-linecap="round" stroke-dasharray='5,10,5' x='20' y='20' onmousedown="selectElement(event)"/>
然后现在我们添加代码来处理选中的元素
var currentX = 0;
var currentY = 0;
var currentMatrix = 0;
function selectElement(evt) {
selectedElement = evt.target;
currentX = evt.clientX;
currentY = evt.clientY;
currentMatrix = selectedElement.getAttributeNS(null, "transform").slice(7,-1).split(' ');
for(var i=0; i<currentMatrix.length; i++) {
currentMatrix[i] = parseFloat(currentMatrix[i]);
}
selectedElement.setAttributeNS(null, "onmousemove", "moveElement(evt)");
selectedElement.setAttributeNS(null, "onmouseout", "deselectElement(evt)");
selectedElement.setAttributeNS(null, "onmouseup", "deselectElement(evt)");
}
现在当我们鼠标按在了元素上(这里是rect),我们需要记录现在是哪一个元素被选中了,并且我们需要知道当前这个元素的transform的值。然后记录鼠标的x,y坐标,这样当我们移动的时候,就可以知道移动了多少,最后,我们给这个元素添加了一个moveElement方法和DeselectElement分别响应鼠标的移动和弹起(松开手指)、移出(超出范围后响应)
下面是拖动的方法
function moveElement(evt) {
var dx = evt.clientX - currentX;
var dy = evt.clientY - currentY;
currentMatrix[4] += dx;
currentMatrix[5] += dy;
selectedElement.setAttributeNS(null, "transform", "matrix(" + currentMatrix.join(' ') + ")");
currentX = evt.clientX;
currentY = evt.clientY;
}
这里也很简单,就是找到当前鼠标的新位置,并且计算出这个位置和前一个记录位置的偏移量,然后把这个值记录在元素的transform数组(从0开始计算)的第四个和第五个值,然后我们更新一下currentX和currentY,这样当我们再次移动的时候,对比的x,y才是正确的。
最后,我们需要完善当鼠标移出或弹起的时候的事件,也就是鼠标跑的太快了,超出当前元素的范围的时候,我们就不要再记录位置,或者当用户的鼠标弹起了,也不能让元素再跟着鼠标跑了,下面是代码。
function deselectElement(evt) {
if(selectedElement != 0){
selectedElement.removeAttributeNS(null, "onmousemove");
selectedElement.removeAttributeNS(null, "onmouseout");
selectedElement.removeAttributeNS(null, "onmouseup");
selectedElement = 0;
}
}
代码量不多,相信大家很容易就看懂了,有说的不对了,欢迎批评指正。