基于zrender实现在canvas中绘制基本图形
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>demo1</title>
<script type="text/javascript" src="js/echarts.js"></script>
</head>
<body>
<div id="main" style="height:600px;width:600px;"></div>
<script type="text/javascript">
var main = echarts.init(document.getElementById('main'));
var option = {
title:{
text:'ECharts demo'
},
legend:{
data:['销量']
},
xAxis:{
data:["衬衫","羊毛衫","雪纺衫","裤子","高跟鞋","袜子"]
},
yAxis:{},
series:[{
name:'销量',
type:'bar',
data:[5,20,36,10,10,20]
}]
};
main.setOption(option);
</script>
<input type="text" id="text"placeholder="请输入文字"/><br/><br/>
<input type="button" name="" value="写入文字" id="btn"/><br/><br/>
<input type="file" id="file"placeholder="请输入图片"/><br/><br/>
<input type="button" name="" value="导入图片" id="btn1"/><br/><br/>
<canvas id="mycv" width="600px" height="600px" style="border:1px solid black">
您的浏览器不支持canvas
</canvas>
<script text="text/javascript">
var canvas1 = document.getElementById("mycv");
var text= document.getElementById("text");
var btn = document.getElementById("btn");
var arr=[];
var imgs=[];//canvas中的所有图像
var img;//当前操作的图像
btn.onclick = function(){
var value = text.value;
if(canvas1.getContext){
var ctx = canvas1.getContext("2d");
ctx.font = "bold 30px arial";
ctx.fillStyle="black";
ctx.fillText(value,150,150);
}
}
var btn1 = document.getElementById("btn1");
btn1.onclick = function(){
let reader = new FileReader();
reader.readAsDataURL(document.querySelector("#file").files[0]);
reader.onload = function (e) {
let result = e.target.result; // base64格式图片地址
img = new Image();
img.src = result; // 设置image的地址为base64的地址
img.onload = function () {
if(canvas1.getContext){
var ctx = canvas1.getContext("2d");
ctx.drawImage(img, 0, 0, 100, 100);
arr.push(ctx.getImageData(0, 0, canvas1.width, canvas1.height));
imgs.push([img,0,0,100,100]);
}
}
};
}
canvas1.onmousedown = function (e) {
let ax, ay, x, y;
canvas1.onmousemove = function (e) {
x = e.clientX;
y = e.clientY;
arr.pop();
imgs.pop();
ctx = canvas1.getContext("2d");
// //先清除之前的然后重新绘制
ctx.clearRect(0, 0, canvas1.width, canvas1.height);
// if (arr.length != 0) {
// ctx.putImageData(arr[arr.length - 1], 0, 0, 0, 0, canvas1.width, canvas1.height);
// }
imgs.forEach(function(item, index){
ctx.drawImage(item[0], item[1], item[2],item[3],item[4]);
});
ctx.drawImage(img, x-50, y-250, 100, 100);
arr.push(ctx.getImageData(0, 0, canvas1.width, canvas1.height));
imgs.push([img,x-50, y-250, 100, 100]);
};
canvas1.onmouseup = function () {
canvas1.onmousemove = null;
canvas1.onmouseup = null;
};
}
</script>
</body>
</html>
var type = "pen";//当前画图的类型
//用于保存所有画出的图形,包括图片
var objs = [];
var canvas;
var zr;
//设置类型
function setType(t){
type=t;
//界面展示当前操作名称
var operate = document.getElementById("operate");
switch(t){
case "img":
operate.innerText="导入图片";
break;
case "pen":
operate.innerText="铅笔";
break;
case "line":
operate.innerText="直线";
break;
case "circle":
operate.innerText="圆";
break;
case "rect":
operate.innerText="矩形";
break;
case "isogon":
operate.innerText="正多边形";
break;
case "":
operate.innerText="移动";
break;
}
//类型为空代表移动,其他时候设置图形不可移动防止画新图形时改变原有图形的位置
objs = zr.storage._displayList;
if(type == ""){
for (let index = 0; index < objs.length; index++) {
var tmpobj = objs[index];
objs[index].attr({"draggable":true})
}
} else{
for (let index = 0; index < objs.length; index++) {
var tmpobj = objs[index];
objs[index].attr({"draggable":false})
}
}
zr.refresh();
}
window.onload = function() {
var btn1 = document.getElementById("btn1");
var saveAndClear = document.getElementById("saveAndClear");
var clear = document.getElementById("clear");
var load = document.getElementById("load");
var undo = document.getElementById("undo");
canvas = document.getElementById('mycv');
zr = zrender.init(canvas);
var obj;//当前画图的对象
var penline=[];
var objParam =[];//保存已画图形的关键元素
var s;//将当前对象序列化后的内容
//保存历史记录,用于撤销绘图
var objsHistory=[];
//清除画布但保留已画对象
saveAndClear.onclick = function(){
objs = zr.storage._displayList;//获取当前画布上的所有内容
for (let index = 0; index < objs.length; index++) {
var elementParam = [];
var element = objs[index];
var elementType = element.__proto__.type;//类型
var transform = element.transform;//平移
elementParam.push(elementType);
switch(elementType){
case "polyline"://曲线
var elementPoints = element.shape.points;
var elementSmooth = element.shape.smooth;
var elementStroke = element.style.stroke;
var elementLineWidth = element.style.lineWidth;
var opts = {
rectHover:true,
shape: {
points:elementPoints,
smooth:elementSmooth
},
style:{
stroke:elementStroke,
lineWidth:elementLineWidth
},
position:[transform == null ? 0 : transform[4], transform == null ? 0 : transform[5]]
}
elementParam.push(opts);
break;
case "line":
var x1 = element.shape.x1;
var x2 = element.shape.x2;
var y1 = element.shape.y1;
var y2 = element.shape.y2;
var elementStroke = element.style.stroke;
var elementLineWidth = element.style.lineWidth;
var opts = {
rectHover:true,
shape: {
x1: x1,
y1: y1,
x2: x2,
y2: y2,
percent:1
},
style:{
stroke:elementStroke,
lineWidth:elementLineWidth
},
position:[transform == null ? 0 : transform[4], transform == null ? 0 : transform[5]]
}
elementParam.push(opts);
break;
case "circle":
var cx = element.shape.cx;
var cy = element.shape.cy;
var r = element.shape.r;
var elementStroke = element.style.stroke;
var elementLineWidth = element.style.lineWidth;
var opts = {
rectHover:true,
shape: {
cx: cx,
cy: cy,
r: r,
},
style:{
fill:"rgba(255,255,255,0",
stroke:elementStroke,
lineWidth:elementLineWidth
},
position:[transform == null ? 0 : transform[4], transform == null ? 0 : transform[5]]
}
elementParam.push(opts);
break;
case "rect":
var x = element.shape.x;
var y = element.shape.y;
var width = element.shape.width;
var height = element.shape.height;
var elementStroke = element.style.stroke;
var elementLineWidth = element.style.lineWidth;
var opts = {
rectHover:true,
shape: {
x: x,
y: y,
width:width,
height:height
},
style:{
fill:"rgba(255,255,255,0",
stroke:elementStroke,
lineWidth:elementLineWidth
},
position:[transform == null ? 0 : transform[4], transform == null ? 0 : transform[5]]
}
elementParam.push(opts);
break;
case "isogon":
var x = element.shape.x;
var y = element.shape.y;
var r = element.shape.r;
var n = element.shape.n;
var elementStroke = element.style.stroke;
var elementLineWidth = element.style.lineWidth;
var opts = {
rectHover:true,
shape: {
x:x,
y:y,
r:r,
n:n
},
style:{
fill:"rgba(255,255,255,0",
stroke:elementStroke,
lineWidth:elementLineWidth
},
position:[transform == null ? 0 : transform[4], transform == null ? 0 : transform[5]]
}
elementParam.push(opts);
break;
case "image":
var x = element.style.x;
var y = element.style.y;
var width = element.style.width;
var height = element.style.height;
var image = element.style.image;
var opts = {
style: {
image:image,
x:100,
y:100,
width:200,
height:200
},
position:[transform == null ? 0 : transform[4], transform == null ? 0 : transform[5]]
}
elementParam.push(opts);
break;
}
objParam.push(elementParam);
}
s = JSON.stringify(objParam)
console.log(s);
zr.clear();
objs=[];
}
//清除画布,不保留已画对象
clear.onclick = function(){
zr.clear();
objs = [];
objsHistory=[];
}
//加载最后一次绘画
load.onclick = function(){
zr = zrender.init(canvas);
objParam = eval('('+s+')');
for (let index = 0; index < objParam.length; index++) {
var element = objParam[index];
var elementType = element[0];
var elementParam = element[1];
switch(elementType){
case "polyline":
obj = new zrender.Polyline(elementParam);
zr.add(obj);
break;
case "line":
obj = new zrender.Line(elementParam);
zr.add(obj);
break;
case "circle":
obj = new zrender.Circle(elementParam);
zr.add(obj);
break;
case "rect":
obj = new zrender.Rect(elementParam);
zr.add(obj);
break;
case "isogon":
obj = new zrender.Isogon(elementParam);
zr.add(obj);
break;
case "image":
obj = new zrender.Image(elementParam);
obj.on("mousewheel", function(params){
var shape = params.target;
var event = params.event;
var delta = event.wheelDelta;
if(delta>0){
img.attr("height",shape.style.height += 10);
img.attr("width",shape.style.width += 10);
} else{
img.attr("height",shape.style.height -= 10);
img.attr("width",shape.style.width -= 10);
}
zr.refresh();
});
zr.add(obj);
break;
}
//添加鼠标双击事件,修改线的宽及颜色
obj.on("dblclick",function(){
var lineWidth = document.getElementById("input2").value;
var color = document.getElementById("input3").value;
this.attr({
style:{
stroke:color,
lineWidth:lineWidth
}
});
});
}
objParam=[]
}
//撤销
undo.onclick = function(){
zr.clear();
objsHistory.pop();
objs = objsHistory[objsHistory.length-1];
if(objs != undefined){
zr = zrender.init(canvas);
for (let index = 0; index < objs.length; index++) {
zr.add(objs[index]);
}
}else{
objs=[];
}
}
//导入图片
btn1.onclick = function(){
type="image";
let reader = new FileReader();
reader.readAsDataURL(document.querySelector("#file").files[0]);
reader.onload = function (e) {
let result = e.target.result; // base64格式图片地址
var img = new zrender.Image({
style: {
image:result,
x:100,
y:100,
width:200,
height:200
}
});
//圖片支持縮放
img.on("mousewheel", function(params){
var shape = params.target;
var event = params.event;
var delta = event.wheelDelta;
if(delta>0){
img.attr("height",shape.style.height += 10);
img.attr("width",shape.style.width += 10);
} else{
img.attr("height",shape.style.height -= 10);
img.attr("width",shape.style.width -= 10);
}
zr.refresh();
});
zr.add(img);
//历史记录中保存当前所有元素的集合,用于撤销操作
objs = zr.storage._displayList;
objsHistory.push(new Array().concat(objs));
};
}
//繪製圖形
canvas.onmousedown = function(e){
var x0, y0;
x0 = e.offsetX;
y0 = e.offsetY;
var lineWidth = document.getElementById("input2").value;
var color = document.getElementById("input3").value;
//圆
if(type == "circle"){
var r=10;
obj = new zrender.Circle({
shape: {
cx: x0,
cy: y0,
r: r
},
style:{
fill:"rgba(255,255,255,0",
stroke:color,
lineWidth:lineWidth
}
});
zr.add(obj);
}
//矩形
if(type == "rect"){
obj = new zrender.Rect({
shape: {
x: x0,
y: y0,
width: 10,
height:10
},
style:{
fill:"rgba(255,255,255,0",
stroke:color,
lineWidth:lineWidth
}
});
zr.add(obj);
}
//正多边形
if(type == "isogon"){
var n = document.getElementById("input1").value;
obj = new zrender.Isogon({
shape: {
x: x0,
y: y0,
r: 10,
n: n
},
style:{
fill:"rgba(255,255,255,0",
stroke:color,
lineWidth:lineWidth
}
});
zr.add(obj);
}
//直线
if(type == "line"){
obj = new zrender.Line({
rectHover:true,
shape: {
x1: x0,
y1: y0,
x2: x0,
y2: y0,
percent:1
},
style:{
stroke:color,
lineWidth:lineWidth
}
});
zr.add(obj);
}
//曲线
if(type == "pen"){
penline.push([x0,y0]);
obj = new zrender.Polyline({
rectHover:true,
shape: {
points:penline,
smooth:0.5
},
style:{
stroke:color,
lineWidth:lineWidth
}
});
zr.add(obj);
}
//定义鼠标移动事件,用于画图
canvas.onmousemove = function(e){
x1 = e.offsetX;
y1 = e.offsetY;
//移动鼠标修改圆的半径
if(type == "circle"){
zr.remove(obj);
var r=Math.sqrt(Math.pow(x0-x1,2)+Math.pow(y0-y1,2));
obj = new zrender.Circle({
shape: {
cx: x0,
cy: y0,
r: r
},
style:{
fill:"rgba(255,255,255,0)",
stroke:color,
lineWidth:lineWidth
}
});
zr.add(obj);
}
//移动鼠标修改矩形长宽
if(type == "rect"){
zr.remove(obj);
obj = new zrender.Rect({
shape: {
x: x0,
y: y0,
width: x1-x0,
height:y1-y0
},
style:{
fill:"rgba(255,255,255,0",
stroke:color,
lineWidth:lineWidth
}
});
zr.add(obj);
}
//修改正多边形大小
if(type == "isogon"){
zr.remove(obj);
var n = document.getElementById("input1").value;
var r=Math.sqrt(Math.pow(x0-x1,2)+Math.pow(y0-y1,2));
obj = new zrender.Isogon({
shape: {
x: x0,
y: y0,
r: r,
n: n
},
style:{
fill:"rgba(255,255,255,0",
stroke:color,
lineWidth:lineWidth
}
});
zr.add(obj);
}
//修改直线的长度及方向
if(type == "line"){
zr.remove(obj);
obj = new zrender.Line({
rectHover:true,
shape: {
x1: x0,
y1: y0,
x2: x1,
y2: y1,
percent:1
},
style:{
stroke:color,
lineWidth:lineWidth
}
});
zr.add(obj);
}
//画曲线
if(type == "pen"){
zr.remove(obj);
penline.push([x1,y1]);
obj = new zrender.Polyline({
rectHover:true,
shape: {
points:penline,
smooth:0.5
},
style:{
stroke:color,
lineWidth:lineWidth
}
});
zr.add(obj);
}
}
//鼠标松开后为元素添加双击事件,历史记录中保存数据方便撤销
canvas.onmouseup = function(e){
canvas.onmousemove = null;
//保存绘画的对象
if(obj != undefined){
//支持修改线宽度
obj.on("dblclick",function(){
var lineWidth = document.getElementById("input2").value;
var color = document.getElementById("input3").value;
this.attr({
style:{
stroke:color,
lineWidth:lineWidth
}
});
});
objs = zr.storage._displayList;
//历史记录中保存当前所有元素的集合,用于撤销操作
objsHistory.push(new Array().concat(objs));
}
//清空铅笔画线的点集
penline=[];
obj = null;
}
}
}