在html页面中直接引入以上两个js即可,就可实现如下功能
1. 点击添加块出现红色的圆形
2. 当鼠标拖拽红色的圆形便会出现x,y轴线随着圆的移动随着他移动
3. 移动图的同时最上方会出现你所移动的坐标数
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>Document</title>
<style type="text/css">
canvas{
background-color: rgb(247, 247, 247);
margin-top: 10px;
border: thin solid blue;
}
</style>
</head>
<body>
<p id="message"></p>
<div class="controls">
网格线<input id="gridCheckBox" type="checkbox" checked="checked" >
坐标轴<input id="axesCheckBox" type="checkbox" checked="checked" >
<!-- 辅助线<input id="guideWiresCheckBox" type="checkbox" checked="checked" > -->
<input type="button" value="清除画布" id="eraseAllButton">
<input type="button" value="添加块" id="addBlock">
</div>
<!--canvas默认大小300*150-->
<canvas id="canvas" width="800" height="500">
</canvas>
</body>
<!--导入绘制坐标、网格的js文件-->
<script type = "text/javascript" src ="mikuCanvasAxes.js"></script>
<!--导入主要绘图js文件-->
<!--
全局变量定义
函数:窗口坐标转换为Canvas坐标、保存\还原当前绘图表面数据、橡皮筋法相关函数、绘制辅助线相关函数、初始化函数
事件处理:鼠标down,move,up事件、按钮点击事件、单选框变化事件
-->
<script type = "text/javascript" src ="mikuCanvasPaintAppMain.js"></script>
</html>
//Classes----------------------------------------------------
function mikuLoc(locX,locY){
this.x = locX;
this.y = locY;
}
//Contents---------------------------------------------------
var GRID_STYLE = "lightgray",
GRID_LINE_WIDTH = 0.5;
var AXES_STYLE = "#a2a2a2",
AXES_LINE_WIDTH = 1,
VERTICAL_TICK_SPACING = 10,
HORIZONTAL_TIKE_SPACING = 10,
TICK_WIDTH = 10;
//Function---------------------------------------------------
//绘制网格
//传入参数为:绘图环境,x轴间隔,y轴间隔
function drawGrid(context,stepx,stepy){
context.save();
context.strokeStyle = GRID_STYLE;
//设置线宽为0.5
context.lineWidth = GRID_LINE_WIDTH;
//绘制x轴网格
//注意:canvas在两个像素的边界处画线
//由于定位机制,1px的线会变成2px
//于是要+0.5
for(var i=stepx+0.5;i<context.canvas.width;i=i+stepx){
//开启路径
context.beginPath();
context.moveTo(i,0);
context.lineTo(i,context.canvas.height);
context.stroke();
}
//绘制y轴网格
for(var i=stepy+0.5;i<context.canvas.height;i=i+stepy){
context.beginPath();
context.moveTo(0,i);
context.lineTo(context.canvas.width,i);
context.stroke();
}
context.restore();
};
//Function---------------------------------------------------
//绘制坐标轴
//传入参数为:绘图环境,坐标轴边距
function drawAxes(context,axesMargin){
//保存样式
context.save();
var originLoc = new mikuLoc(axesMargin, context.canvas.height-axesMargin);
var axesW = context.canvas.width - (axesMargin*2),
axesH = context.canvas.height - (axesMargin*2);
//设置坐标绘图样式绘图样式
context.strokeStyle = AXES_STYLE;
context.lineWidth = AXES_LINE_WIDTH;
//绘制x,y轴
drawHorizontalAxis();
drawVerticalAxis();
drawVerticalAxisTicks();
drawHorizontalAxisTicks();
//恢复样式
context.restore();
//绘制x轴
function drawHorizontalAxis(){
context.beginPath();
context.moveTo(originLoc.x, originLoc.y);
context.lineTo(originLoc.x + axesW, originLoc.y);
context.stroke();
}
//绘制y轴
function drawVerticalAxis(){
context.beginPath();
context.moveTo(originLoc.x, originLoc.y);
context.lineTo(originLoc.x, originLoc.y - axesH);
context.stroke();
}
//绘制垂直轴小标标
function drawVerticalAxisTicks(){
var deltaX;
//当前垂直tick的y轴坐标
var nowTickY =originLoc.y-VERTICAL_TICK_SPACING;
for(var i=1;i<=(axesH/VERTICAL_TICK_SPACING);i++){
if(i%5 === 0){
deltaX=TICK_WIDTH;
}else {
deltaX=TICK_WIDTH/2;
}
context.beginPath();
//移动到当前的tick起点
context.moveTo(originLoc.x-deltaX,nowTickY);
context.lineTo(originLoc.x+deltaX,nowTickY);
context.stroke();
nowTickY=nowTickY-VERTICAL_TICK_SPACING;
}
}
//绘制水平轴小标标
function drawHorizontalAxisTicks(){
var deltaY;
var nowTickX = originLoc.x+HORIZONTAL_TIKE_SPACING;
for(var i=1;i<=(axesW/HORIZONTAL_TIKE_SPACING);i++){
if(i%5 === 0){
deltaY = TICK_WIDTH;
}else{
deltaY = TICK_WIDTH/2;
}
context.beginPath();
context.moveTo(nowTickX,originLoc.y+deltaY);
context.lineTo(nowTickX,originLoc.y-deltaY);
context.stroke();
nowTickX = nowTickX + HORIZONTAL_TIKE_SPACING;
}
}
};
//Vars--------------------------------------------------------
var canvas =document.getElementById("canvas"),
context =canvas.getContext("2d"),
//正在绘制的绘图表面变量
drawingSurfaceImageData,
//鼠标按下相关对象
mousedown = {},
//橡皮筋矩形对象
rubberbandRect = {},
//拖动标识变量
dragging = false;
//控件
//擦除画布的控制
var eraseAllButton = document.getElementById("eraseAllButton");
//坐标轴的控制
var axesCheckBox = document.getElementById("axesCheckBox");
//网格线的控制
var gridCheckBox = document.getElementById("gridCheckBox");
//辅助线的控制
var guideWiresCheckBox = document.getElementById("guideWiresCheckBox");
//线条颜色的控制
var strokeColorSelectBox =document.getElementById("strokeColorSelectBox");
//线条样式的控制
var lineTypeSelectBox = document.getElementById("lineTypeSelectBox");
//线条宽度的控制
var lineWidthSelectBox = document.getElementById("lineWidthSelectBox");
//添加块
var addBlock = document.getElementById('addBlock');
//Functions---------------------------------------------------
function getLocation(x, y) {
var bbox = canvas.getBoundingClientRect();
return {
x: (x - bbox.left) * (canvas.width / bbox.width),
y: (y - bbox.top) * (canvas.height / bbox.height)
/*
* 此处不用下面两行是为了防止使用CSS和JS改变了canvas的高宽之后是表面积拉大而实际
* 显示像素不变而造成的坐标获取不准的情况
x: (x - bbox.left),
y: (y - bbox.top)
*/
};
}
//将窗口坐标转换为Canvas坐标
//传入参数:窗口坐标(x,y)
function windowToCanvas(x,y){
//获取canvas元素的边距对象
var bbox = canvas.getBoundingClientRect();
//返回一个坐标对象
//类似json的一种写法
return {
x : x - bbox.left*(canvas.width/bbox.width),
y : y - bbox.top*(canvas.height/bbox.height)
};
}
//保存当前绘图表面数据
function saveDrawingSurface(){
//从上下文中获取绘图表面数据
drawingSurfaceImageData = context.getImageData(0,0,canvas.width,canvas.height);
}
//还原当前绘图表面
function restoreDrawingSurface(){
//将绘图表面数据还原给上下文
context.putImageData(drawingSurfaceImageData,0,0);
}
//橡皮筋相关函数
//更新橡皮筋矩形+对角线
//传入参数:坐标对象loc
function updateRubberband(loc){
updateRubberbandRectangle(loc);
drawRubberbandShape(loc);
}
//更新橡皮筋矩形
//传入参数:坐标对象loc
function updateRubberbandRectangle(loc){
//获得矩形的宽
rubberbandRect.width = Math.abs(loc.x - mousedown.x);
//获得矩形的高
rubberbandRect.height = Math.abs(loc.y - mousedown.y);
//获得矩形顶点的位置(left,top)
//如果鼠标按下的点(起点)在当前点的的左侧
//这里画一下图就懂了
if(loc.x > mousedown.x){
rubberbandRect.left = mousedown.x;
}else{
rubberbandRect.left = loc.x;
}
if(loc.y > mousedown.y){
rubberbandRect.top = mousedown.y;
}else{
rubberbandRect.top = loc.y;
}
}
//绘制橡皮筋矩形的对角线
//传入参数:坐标对象loc
function drawRubberbandShape(loc){
//获取当前线条类型
var lineType = lineTypeSelectBox.value;
//获取当前线条颜色
var lineColor = strokeColorSelectBox.value;
//获取当前线条宽度
var lineWidth = lineWidthSelectBox.value;
//有改变context画笔属性就要做画笔保护
context.save();
context.strokeStyle = lineColor;
context.lineWidth = lineWidth;
if(lineType === "solid"){
//alert("draw");
//注意重新开始路径
context.beginPath();
context.moveTo(mousedown.x,mousedown.y);
//这里可以更改成画虚线
context.lineTo(loc.x,loc.y);
context.stroke();
}else if(lineType === "dashed"){
drawDashedLine(context,mousedown.x,mousedown.y,loc.x,loc.y);
}
context.restore();
}
//绘制辅助用的线-------------------------
//绘制水平线
function drawHorizontalLine(y){
// context.beginPath();
// context.moveTo(0,y+0.5);
// context.lineTo(context.canvas.width,y+0.5);
// context.stroke();
context.beginPath();
context.moveTo(0, y);
context.lineTo(canvas.width, y);
context.stroke();
context.closePath();
}
//绘制垂直线
function drawVerticalLine(x){
// context.beginPath();
// context.moveTo(x+0.5,0);
// context.lineTo(x+0.5,context.canvas.height);
// context.stroke();
context.beginPath();
context.moveTo(x, 0);
context.lineTo(x, canvas.height);
context.stroke();
context.closePath();
}
//绘制辅助用的线
function drawGuideWires(x,y){
//画笔保护
context.save();
context.strokeStyle = "red";
context.lineWidth = 0.5;
drawHorizontalLine(y);
drawVerticalLine(x);
context.restore();
}
//初始化函数
function initialization(){
//清除画布
context.clearRect(0,0,canvas.width,canvas.height);
//绘制网格与坐标的颜色是默认的
if(axesCheckBox.checked){
drawAxes(context,40);
}
if(gridCheckBox.checked){
drawGrid(context,10,10);
}
}
//Event Hander-----------------------------------------------------
var timeOutEvent = 0; //区分拖拽和点击的参数
var r = 30;
canvas.onmousedown = function(e){
// var loc =windowToCanvas(e.clientX,e.clientY);
// e.preventDefault();
// saveDrawingSurface();
// mousedown.x = loc.x;
// mousedown.y = loc.y;
var e = e || event;
var x = e.layerX;
var y = e.layerY;
timeOutEvent = setTimeout("longPress()", 500);
e.preventDefault();
drag(x, y, r);
dragging = true;
}
//创建图形
function createBlock(a, b, r) {
context.beginPath();
context.fillStyle = "red";
context.arc(a, b, r, 0, Math.PI * 2);
context.fill();
}
//拖拽函数
function drag(x, y, r) {
console.log(x,y)
// 按下鼠标判断鼠标位置是否在圆上,当画布上有多个路径时,isPointInPath只能判断最后那一个绘制的路径
if (context.isPointInPath(x, y)) {
//路径正确,鼠标移动事件
canvas.onmousemove = function (ev) {
var e = ev || event;
ax = e.layerX;
ay = e.layerY;
console.log(ax, ay)
clearTimeout(timeOutEvent);
timeOutEvent = 0;
//鼠标移动每一帧都清楚画布内容,然后重新画圆
context.clearRect(0, 0, canvas.width, canvas.height);
// var location = getLocation(ax, ay);
var message = document.getElementById("message");
message.innerHTML = "x=" + ax + " ,y=" + ay;
// context.clearRect(0, 0, canvas.width, canvas.height);
initialization();
drawHorizontalLine(ay-r);
drawVerticalLine(ax-r);
createBlock(ax, ay, r);
};
//鼠标移开事件
canvas.onmouseup = function () {
canvas.onmousemove = null;
canvas.onmouseup = null;
clearTimeout(timeOutEvent);
// if (timeOutEvent != 0) {
// alert("你这是点击,不是拖拽");
// }
}
}
}
function longPress() {
timeOutEvent = 0;
}
/*
canvas.onmousemove = function(e){
var loc;
if(dragging){
e.preventDefault();
// loc = windowToCanvas(e.clientX,e.clientY);
// restoreDrawingSurface();
// updateRubberband(loc);
}
if(dragging&&guideWiresCheckBox.checked){
// drawGuideWires(loc.x,loc.y);
}
// by luyao
if(guideWiresCheckBox.checked){
loc = windowToCanvas(e.clientX,e.clientY);
//restoreDrawingSurface();
drawGuideWires(loc.x,loc.y);
}
}
canvas.onmouseup = function(e){
// loc = windowToCanvas(e.clientX,e.clientY);
// restoreDrawingSurface();
// updateRubberband(loc);
dragging = false;
}
*/
//点击添加一个块
addBlock.onclick = function () {
createBlock(200,200,30)
}
//需要擦除的操作需要重新初始化
eraseAllButton.onclick = function(e){
context.clearRect(0,0,canvas.width,canvas.height);
initialization();
saveDrawingSurface();
}
axesCheckBox.onchange = function(e){
initialization();
}
gridCheckBox.onchange = function(e){
initialization();
}
//Mian----------------------------------------------
initialization();