canvas

570 阅读6分钟

一、canvas的其他属性

var c = document.getElementById('myCanvas1')
       // 改变宽度清空画布
       c.width = c.width
       var ogc = c.getContext('2d') //返回一个用于在画布上绘图的环境
       ogc.beginPath() //开始一条路径 背景
       ogc.arc(40, 40, 35, 0, 2 * Math.PI) // 画圆值为 圆的中心的 x 坐标,y坐标,半径,起点(3点为0PI),
       ogc.strokeStyle = '#45126A' //路径的样式
       ogc.lineWidth = 10
       ogc.stroke() //使用 stroke() 方法在画布上绘制确切的路径。
       var ctx = c.getContext('2d')
       ctx.beginPath() //高亮环路径
       ctx.arc(40, 40, 35, -Math.PI / 2, (a * 3.6 - 90) * Math.PI / 180) 
       ctx.strokeStyle = '#FEB09F'//设置或返回用于笔触的颜色、渐变或模式/创建 pattern 笔触的 pattern 对象
       ctx.lineWidth = 10
       ctx.lineCap = 'butt' //butt平直 round圆 square方
       // 设置文字居中但是fillText的第二个参数必须为画布宽度一半
       ctx.textAlign = 'center'
       ctx.font = 'bold 16px Arial'
       ctx.fillStyle = '#FFFFFF'
       ctx.fillText(a + '%', 44, 35) //fillText里面的可填写的值是,文本内容,x坐标,y坐标,文本最大宽度
       ctx.font = '14px Arial'
       ctx.fillStyle = '#FFFFFF'
       ctx.fillText(num + '次', 44, 50)
       ctx.stroke()

注意:文字居中但是fillText的第二个参数必须为画布宽度一半,而且要先设定textAlign ,然后再设定fillText,否则无效,原因的话emmm,我也不知道,但是我试过确实是要先这样,然后那样,就成功了

二、总结以下三种清空canvas画布的方式:

  1. 最简单的方法:由于canvas每当高度或宽度被重设时,画布内容就会被清空,因此可以用以下方法清空:
[javascript] view plain copy
function clearCanvas()
{  
    var c=document.getElementById("myCanvas");  
    var cxt=c.getContext("2d");  
    c.height=c.height;  
}  
  1. 使用clearRect方法:
[javascript] view plain copy
function clearCanvas()  
{  
    var cxt=document.getElementById("myCanvas").getContext("2d");
    cxt.clearRect(0,0,c.width,c.height);  
}  
  1. 类似于方法2,可以用某一特定颜色填充画布,从而达到清空的目的:
[javascript] view plain copy
function clearCanvas()  
{  
    var c=document.getElementById("myCanvas");  
    var cxt=c.getContext("2d");  
      
    cxt.fillStyle="#000000";  
    cxt.beginPath();  
    cxt.fillRect(0,0,c.width,c.height);  
    cxt.closePath();  
}  

清除轨迹的代码

clearRect() 方法清空给定矩形内的指定像素;也可以直接清除其他绘制的比如fillText,只要设置的面积足够大或者是之前绘制的坐标位置都可以

三、解决fillText绘制清除的不是绘制的对象问题

let lnglatUin=[];定义了数组,把站点的所有的经纬度都放进去,方便下面绘制的时候使用
        for(let m of station){
          let lnglat = new AMap.LngLat(m.geo.lng, m.geo.lat);
          lnglatUin.push(lnglat);
        }
        if(pollut) {
           for(let m of lnglatUin) {
            let pixel=this.map.lngLatToContainer(m);经纬度转换成坐标
            ctx.fillText('2',pixel.x,pixel.y);绘制文字
           }
        } else {
          for(let m of lnglatUin) {
            let pixel=this.map.lngLatToContainer(m);经纬度转换成坐标
            ctx.clearRect(0,0,10000,10000);//清除轨迹 清除文字,这里不起作用,放到绘制文字下面是起作用的
           }  
        }
  • 首先判断if else是否能进入
  • 清除轨迹是否生效
  • 确定你的ctx是一个吗; 解决办法:实例化的时候canvas加一个随机id,console出来看一下
  • 确实不是一个 解决办法:保证是同一个啊,哪怕在全局绑一个也行,随便找一个固定的东西,挂个变量挂在全局下 如果有就不直接创建了 用上一个,append一次,你绑定在外面,不要每次执行的时候新建,
//点击直观添加text标签的定义
let canvasText = document.createElement('canvas');//创建变量
//document.getElementById('#container').appendChild(canvasText);
canvasText.id = randomRangeId(10);//绑定随机ID
console.log(canvasText);
let ctxText = canvasText.getContext("2d");
 //生成随机ID
 function randomRangeId(num){
  var returnStr = "",       
      charStr = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; 
  for(var i=0; i<num; i++){
      var index = Math.round(Math.random() * (charStr.length-1));
      returnStr += charStr.substring(index,index+1);
  }
  return returnStr;
}

四、canvas绘制三角形

// 三角形污染源,绘制3个点,点坐标是根据原点加减widht/2的值,直接绘制的
//如果更改形状就更改这和下面引用的地方
function sanjiaoTh(ctx, x, y, width, height) {
  console.log(width);
  ctx.beginPath();
  ctx.moveTo(x,y-height/2); //从A(100,0)开始
  ctx.lineTo(x-width/2,y+height/2);//从A(100,0)开始,画到B (0,173)结束
  ctx.lineTo(x+width/2,y+height/2); //B(0,173)-C(200,173)
  ctx.fill(); //闭合形状并且以填充方式绘制出来
  ctx.closePath();
}

sanjiaoTh(ctx, 100, 100, 36, 36);

特别注意:以上是以center为中心的,center = X +width/2

function draw() { 
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.moveTo(20,20);  //绘制起始点
ctx.lineTo(10,90);
ctx.lineTo(90,90);
// ctx.fill();   //填充
![Uploading 45416FA1-329C-4054-A94A-08B732DF8B3B_494408.png . . .]
ctx.lineWidth = 10;  //线的宽度
ctx.strokeStyle = 'red';  // 线的颜色变红
ctx.lineJoin = 'round';  //设置线的圆角   用于转交和两条线的交接点
// ctx.lineCap = 'round';  //设直线的
ctx.closePath(); //结束绘制
ctx.stroke(); //划线   连接点  划线


ctx.beginPath();
ctx.moveTo(120,120);  //绘制起始点,这里都是坐标,坐标不是长度和宽度
ctx.lineTo(150,190);
ctx.lineTo(230,190);
ctx.fill();   //填充
ctx.lineJoin = 'round';  //设置线的圆角   用于转交和两条线的交接点
}

效果如下

五、canvas 在页面上不显示效果解决办法

得调用出函数;有没有执行方法 页面dom里有没有canvas,看dom,可以给他赋值ID,然后在谷歌浏览器的Elements中搜索这个ID就知道了;canvas.id="" canvas有没有画上 画的位置是不是不对,比如有没有超出canvas画布,画的内容超出画布了 肯定也显示不上,先确认canvas在不在页面 然后在手动在canvas的0,0位置画个正方形看有没有 没别的可能了

canvas在地图里仅仅支持经纬度,需要做经纬度转换成坐标

经纬度坐标转容器坐标 map.lngLatToContainer(高德地图官方文档上有) // 地理经纬度坐标 var lon = 116.4;// longitude经度 var lat = 39.9;//latitude纬度

// 构造成 LngLat 对象后传入 var lnglat = new AMap.LngLat(lon, lat); var pixel = map.lngLatToContainer(lnglat); // 获得 Pixel 对象

//arr.splice(2,1);// 去掉数组 height值 //arr.reverse();

//单数据成功
// 地理经纬度坐标
// const lon = 116.4;
// const lat = 39.9;
// // 构造成 LngLat 对象后传入
// let lnglat = new AMap.LngLat(lon, lat);
// let pixel = this.map.lngLatToContainer(lnglat);  // 获得 Pixel 对象
// ctx.fillText("2",pixel.x,pixel.y);

绘制三角形

//===============基本绘制api====================
//获得画布
var canvas = document.querySelector('#cavsElem');
var ctx = canvas.getContext('2d'); //获得上下文

canvas.width = 900; //设置标签的属性宽高
canvas.height = 600; //千万不要用 canvas.style.height
canvas.style.border = '1px solid #000';

canvas 坐标系,从最左上角 0,0 开始。x 向右增大, y 向下增大

//绘制三角形
ctx.beginPath(); //开始路径
ctx.moveTo(100, 100); //三角形,左顶点
ctx.lineTo(300, 100); //右顶点
ctx.lineTo(300, 300); //底部的点
ctx.closePath(); //结束路径
ctx.stroke(); //描边路径
ctx.fillStyle="green";//填充的颜色
ctx.fill();//将颜色填充上

function smile(){
  ctx.beginPath();
  ctx.arc(150,150,80,0,2*Math.PI,false);//创建圆,请把起始角设置为 0,结束角设置为 2*Math.PI,中心的 x,y 坐标,r圆半径,sAngle	起始角,eAngle	结束角,以弧度计。counterclockwise顺时针
  ctx.moveTo(126,130);//将连接线去掉
  ctx.arc(120,130,6,0,2*Math.PI,true);//眼睛
  ctx.moveTo(186,130);
  ctx.arc(180,130,6,0,2*Math.PI,true);//眼睛
  ctx.moveTo(206,150);
  ctx.arc(150,150,56,0,1*Math.PI,false);//嘴巴
  ctx.strokeStyle="rgba(0,0,200,0.8)";
  ctx.stroke();
   }

一步步的去绘制的时候需要每一步都去填充颜色,否则就会仅仅显示最后一个形状;

写的具体样例详见aqmap的Marker中pollution

六、绘制特殊图标,比如污染源的图标

1、画好了存在问题,因为经纬度相同,导致同一个位置会绘制多次,增肌关系是,1234,但是悬浮上去显示的信息的图层是只有1的,其他不显示

2.绘制方式 有2个对象 一个是是放的canvas最基础的绘制方式,每个对象最后都得填充颜色 一个是复杂的操作步骤,比如污染源的图标是有圆和三角,矩形组成了,这就仅仅写调用,具体调用另外一个对象方法