在我的基于SVG的Web应用程序中,用户可以选择大量的形状(甚至800或更多)和在屏幕上移动它们,人们可以想象会严重影响帧速率。在阅读了requestAnimationFrame
的优点之后,我从昨天起就开始尝试将其合并到我的mousemove
函数中,希望通过使用节流和放大器的组合。 requestAnimationFrame
,我可以达到平滑的帧速率。
Here是我在mousemove
移动600 svg形状的jsFiddle。暂时忽略限制,如何将requestAnimationFrame
合并到mousemove
函数中。
http://jsfiddle.net/rehankhalid/5t5pX/
HTML CODE
<svg width="1200" height="800">
<symbol>
<g id="symbol1">
<path fill="#3ab6d1" d="M27.7,1.1C16-2,3.9,5.1,0.8,16.9s4,23.8,15.7,26.9c11.7,3.1,23.8-4,26.9-15.7C46.6,16.3,39.6,4.2,27.7,1.1z M38.3,26.9C36,35.7,26.9,41,18,38.7C9.1,36.4,3.8,27.3,6.1,18.5C8.4,9.6,17.5,4.3,26.4,6.6C35.3,9,40.6,18,38.3,26.9z"/>
<g fill="#d5e1db">
<path d="m25.8,.8c2.5,.4 4.8,1.2 7,2.5l-2.9,4.6c-1.5-.8-3.1-1.4-4.8-1.7l.7-5.4z"/>
<path d="m13.9,2.2l1.7,5.1c-1.5,.7-3,1.5-4.3,2.7l-3.8-3.9c.9-.8 1.9-1.5 2.9-2.2 1.2-.7 2.3-1.3 3.5-1.7z"/>
</g>
<path fill="#196275" d="m26.4,38.5l1.8,5.2c-2.5,.7-4.9,.9-7.4,.8l.6-5.4c1.6,0 3.3-.2 5-.6z"/>
<path fill="#42aec2" d="M6.1,18.4C8.4,9.5,17.5,4.2,26.4,6.5S40.7,18,38.4,26.8C36,35.7,26.9,41,18,38.7C9.1,36.3,3.7,27.2,6.1,18.4 z"/>
<path fill="#d2dfdd" d="m28.7,25.9l.5-4.9 9.5-1.3c0,.3 .1,.6 .2,.8 .4,2.9 0,5.8-1,8.3l-9.2-2.9z"/>
<path fill="#1b6273" d="m19.7,29.3h4.9l2.1,9.4c-.3,.1-.6,.2-.8,.2-2.9,.6-5.7,.5-8.4-.3l2.2-9.3z"/>
<path fill="#368098" d="m15.9,25.8l3.6,3.4-4.8,8.3c-.3-.1-.5-.3-.8-.4-2.6-1.5-4.6-3.5-6-5.9l8-5.4z"/>
<path fill="#d2dfdd" d="m18.6,16.5l-3,3.9-8.7-4c.1-.3 .2-.5 .3-.8 1.2-2.7 3.1-4.9 5.3-6.5l6.1,7.4z"/>
<path fill="#bde2e9" d="m26.4,32.1l-8.4-.5-4.9-6.8 2.3-8 7.7-3.2 7.3,4 1.5,8.2-5.5,6.3z"/>
</g>
</symbol>
<g id="default">
<g id="my-element">
</g>
</g>
<g id="draggroup">
</g>
</svg>
的Javascript
document.addEventListener('mousedown', mousedown, false);
var element = document.getElementById('my-element');
var defaultg = document.getElementById('default');
var mainsvg = document.getElementsByTagName('svg')[0];
var draggroup = document.getElementById('draggroup');
var svgns = "http://www.w3.org/2000/svg";
var x = 0, y = 0;
var scale = '0.25';
for (var i = 0; i < 600; i++) {
var useelement = document.createElementNS(svgns, "use");
useelement.setAttributeNS('http://www.w3.org/1999/xlink', 'href', '#symbol1');
useelement.setAttribute('transform', 'translate(' + x + ',' + y + ') scale(' + scale + ')');
x += 12;
if (x === 240) {
x = 0;
y += 12;
}
element.appendChild(useelement);
}
var bbox = element.getBBox();
var selectionRect = document.createElementNS(svgns, "rect");
selectionRect.setAttribute('id', 'selectionrect');
selectionRect.setAttribute('x', bbox.x);
selectionRect.setAttribute('y', bbox.y);
selectionRect.setAttribute('width', bbox.width);
selectionRect.setAttribute('height', bbox.height);
selectionRect.setAttribute('fill', 'grey');
selectionRect.setAttribute('opacity', '0.2');
draggroup.appendChild(selectionRect);
var dx = 0, dy = 0, mx = 0, my = 0;
var rectdx = 0, rectdy = 0;
var elementdx = 0, elementdy = 0;
function getSvgCordinates(event) {
var m = mainsvg.getScreenCTM();
var p = mainsvg.createSVGPoint();
var x, y;
x = event.pageX;
y = event.pageY;
p.x = x;
p.y = y;
p = p.matrixTransform(m.inverse());
x = p.x;
y = p.y;
x = parseFloat(x.toFixed(3));
y = parseFloat(y.toFixed(3));
return {x: x, y: y};
}
function mousedown(event) {
if (event.target.id === 'selectionrect') {
var svgXY = getSvgCordinates(event);
mx = svgXY.x; // mouse down x
my = svgXY.y;// mouse down y
draggroup.appendChild(element);
document.addEventListener('mousemove', mousemove, false);
document.addEventListener('mouseup', mouseup, false);
}
}
function mouseup() {
document.removeEventListener('mousemove', mousemove, false);
document.removeEventListener('mouseup', mouseup, false);
draggroup.setAttribute('transform', 'translate(0,0)');
rectdx += dx;
rectdy += dy;
elementdx += dx;
elementdy += dy;
selectionRect.setAttribute('transform', 'translate(' + rectdx + ',' + rectdy + ')');
element.setAttribute('transform', 'translate(' + elementdx + ',' + elementdy + ')');
defaultg.appendChild(element);
dx = 0;
dy = 0;
}
function mousemove(event) {
var svgXY = getSvgCordinates(event);
dx = svgXY.x - mx;
dy = svgXY.y - my;
draggroup.setAttribute('transform', 'translate(' + dx + ',' + dy + ')');
}
答案 0 :(得分:1)
基本上,您需要将draggroup.setAttribute()
次呼叫转移到另一个功能。由于您只需要在鼠标停止时进行动画处理,因此请添加另一个变量来指示您是否要拖动,并且只有在这种情况下才会调用requestAnimationFrame
。
var isDragging = false;
function update() { // New function
if (isDragging) {
requestAnimationFrame(update); // Call self again, if still dragging
}
draggroup.setAttribute('transform', 'translate(' + dx + ',' + dy + ')');
}
function mousedown(event) {
if (event.target.id === 'selectionrect') {
isDragging = true;
requestAnimationFrame(update); // Start animation loop
// existing logic here...
}
}
function mouseup() {
isDragging = false;
// existing logic here...
}
您已将该群组的更新位置(dx
,dy
)存储在单独的变量中,因此请从draggroup.setAttribute()
移除mousemove()
来电,添加上述修改,你应该是好的!