如何使所有绘制的(矩形、圆形、线条、多边形)可拖动?纯JS
Posted
技术标签:
【中文标题】如何使所有绘制的(矩形、圆形、线条、多边形)可拖动?纯JS【英文标题】:How to make all drawn (rectangle, circles, lines, polygon) draggable? Pure JS 【发布时间】:2015-06-09 00:16:45 【问题描述】:我有一个简单的画布 html5。它可以通过选择选项绘制一些形状,如线条、圆形、矩形、多边形,但现在我想让所有绘制都可拖动,如果可能的话可调整大小,没有 3 部分库,只有纯 JS。
var canvas,
context,
dragStartLocation,
snapshot;
dragdrop = false;
isDrag = false;
function resizeCanvas()
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
function getCanvasCoordinates(event)
var x = event.clientX - canvas.getBoundingClientRect().left;
y = event.clientY - canvas.getBoundingClientRect().top;
return x: x, y: y;
function takeSnapshot()
snapshot = context.getImageData(0, 0, canvas.width, canvas.height);
function restoreSnapshot()
context.putImageData(snapshot, 0, 0);
function drawLine(position)
context.beginPath();
context.moveTo(dragStartLocation.x, dragStartLocation.y);
context.lineTo(position.x, position.y );
context.stroke();
function drawRect(position)
context.beginPath();
//context.moveTo(dragStartLocation.x, dragStartLocation.y);
context.fillRect(position.x, position.y, dragStartLocation.x - position.x, dragStartLocation.y - position.y);
//context.stroke();
function drawCircle(position)
var radius = Math.sqrt(Math.pow((dragStartLocation.x - position.x), 2) + Math.pow((dragStartLocation.y - position.y), 2));
context.beginPath();
context.arc(dragStartLocation.x, dragStartLocation.y, radius, 0, 2 * Math.PI, false);
/*
function drawPolygon(position, sides, angle)
var coordinates = [],
radius = Math.sqrt(Math.pow((dragStartLocation.x - position.x), 2) + Math.pow((dragStartLocation.y - position.y), 2)),
index = 0;
for (index = 0; index < sides; index++)
coordinates.push(x: dragStartLocation.x + radius * Math.cos(angle), y: dragStartLocation.y - radius * Math.sin(angle));
angle += (2 * Math.PI) / sides;
context.beginPath();
context.moveTo(coordinates[0].x, coordinates[0].y);
for (index = 1; index < sides; index++)
context.lineTo(coordinates[index].x, coordinates[index].y);
context.closePath();
*/
function draw(position)
var fillBox = document.getElementById("fillBox"),
shape = document.querySelector('#tools option:checked').value,
/*polygonSides = document.getElementById("polygonSides").value,
polygonAngle = document.getElementById("polygonAngle").value,*/
lineCap = document.querySelector('input[type="radio"][name="lineCap"]:checked').value;
/*composition = document.querySelector('input[type="radio"][name="composition"]:checked').value;*/
context.lineCap = lineCap;
/*context.globalCompositeOperation = composition;*/
if (shape === "circle")
drawCircle(position);
if (shape === "line")
drawLine(position);
if (shape === "rect")
drawRect(position);
if (shape === "polygon")
drawPolygon(position, polygonSides, polygonAngle * (Math.PI / 180));
if (shape !== "line")
if (fillBox.checked)
context.fill();
else
context.stroke();
function dragStart(event)
dragging = true;
dragStartLocation = getCanvasCoordinates(event);
takeSnapshot();
function drag(event)
var position;
if (dragging === true)
restoreSnapshot();
position = getCanvasCoordinates(event);
draw(position);
function dragStop(event)
dragging = false;
restoreSnapshot();
var position = getCanvasCoordinates(event);
draw(position);
function changeLineWidth()
context.lineWidth = this.value;
event.stopPropagation();
function changeFillStyle()
context.fillStyle = this.value;
event.stopPropagation();
function changeStrokeStyle()
context.strokeStyle = this.value;
event.stopPropagation();
function changeBackgroundColor()
context.save();
context.fillStyle = document.getElementById("backgroundColor").value;
context.fillRect(0, 0, canvas.width, canvas.height);
context.restore();
function eraseCanvas()
context.clearRect(0, 0, canvas.width, canvas.height);
function init()
canvas = document.getElementById("canvas");
context = canvas.getContext('2d');
var lineWidth = document.getElementById("lineWidth"),
fillColor = document.getElementById("fillColor"),
strokeColor = document.getElementById("strokeColor"),
//canvasColor = document.getElementById("backgroundColor"),
clearCanvas = document.getElementById("clearCanvas");
//saveCanvas = document.getElementById("saveCanvas");
context.strokeStyle = strokeColor.value;
context.fillStyle = fillColor.value;
context.lineWidth = lineWidth.value;
/*window.addEventListener('resize', resizeCanvas, false);
window.addEventListener('orientationchange', resizeCanvas, false);
resizeCanvas();*/
canvas.addEventListener('mousedown', dragStart, false);
canvas.addEventListener('mousemove', drag, false);
canvas.addEventListener('mouseup', dragStop, false);
lineWidth.addEventListener("input", changeLineWidth, false);
fillColor.addEventListener("input", changeFillStyle, false);
strokeColor.addEventListener("input", changeStrokeStyle, false);
//canvasColor.addEventListener("input", changeBackgroundColor, false);
clearCanvas.addEventListener("click", eraseCanvas, false);
//saveCanvas.addEventListener("click", salvaCanvas, false);
window.addEventListener('load', init, false);
【问题讨论】:
*** 上有很多(几十个?)与“拖动”画布绘图相关的问题/答案。我怀疑搜索会很快显示您需要的代码;-) 【参考方案1】:canvas 的一个基本特性是它只存储由所有绘制操作形成的光栅图像。这就是为什么 canvas 速度快且内存效率高的原因。
缺点是您必须擦除画布上受影响的矩形(或最坏情况下的整个画布)并重新绘制所有需要调整大小、移动等的形状。画布不会将它们存储为对象,因此您的 JS 代码必须负责在画布上存储、修改和重新绘制它们。除非您使用某些第三方库,否则工作量很大。
另一种方法是使用 HTML5 的类似 SVG 的功能而不是画布:<line>
、<path>
、<rect>
等。它们由浏览器作为对象保存并通过 DOM 访问。然而,这是一种完全不同的方法,需要完全重写您的代码。
【讨论】:
可拖动 SVG 的示例可以在 here 找到。没有使用任何库,甚至 jQuery。 但是在我的代码中是否可以适应呢?如果我使用第三方库行 jcanvas,我如何才能将它与我的代码一起使用,仅用于拖放? SVG 方法是您的替代方法,我认为没有办法将两者结合起来。可以继续使用画布,但是您的脚本必须保留所有绘制形状的列表,检测正在拖动/调整大小的形状,并在鼠标移动时重新绘制所有形状。不幸的是,我在纯 JS 中没有现成的解决方案。 @MikeBessonov。支持您引用的 Peter Collingridge 的文章,它提供了一种简洁的方式来拖动没有 jQuery 的 SVG 元素 :-) 顺便说一句,提问者似乎想要将 SVG 导出为图像,讽刺的是,这会让您重新使用画布元素作为出口车辆。 ;-) @markE。好点子。如果最终目的是将草图导出为光栅,那么我仍然会在矢量 (SVG) 中对其进行编辑,最后只需将 SVG 图像拍到画布上并让浏览器渲染它,如 getcontext.net/read/svg-images-on-a-html5-canvas 中所述.以上是关于如何使所有绘制的(矩形、圆形、线条、多边形)可拖动?纯JS的主要内容,如果未能解决你的问题,请参考以下文章