canvas20181114
1. canvas 描边、填充、画线、闭合路径、非零环绕原则
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>canvas</title>
- </head>
- <style>
- canvas {
- border: 1px solid red;
- }
- </style>
- <body>
- <canvas id="can" width="300" height="300"></canvas>
- <p class="juxing">矩形</p>
- <p class="triangle">三角形锯齿问题</p>
- <p class="triangle2">三角形闭合没锯齿,填充色</p>
- <p class="middleEmpty">中空矩形</p>
- <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
- <script>
- let cvs = document.getElementById('can')
- let ctx = cvs.getContext('2d')
- $('.juxing').click(function () {
- a(ctx)
- })
- $('.triangle').click(function () {
- b(ctx)
- })
- $('.triangle2').click(function () {
- c(ctx)
- })
- $('.middleEmpty').click(function () {
- middleEmpty(ctx)
- })
- /**
- * 矩形
- * @param ctx
- */
- function a (ctx) {
- ctx.beginPath()
- // 初始位置
- ctx.moveTo(10, 10)
- // 线条
- ctx.lineTo(110, 10)
- ctx.lineTo(110, 110)
- ctx.lineTo(10, 110)
- ctx.lineTo(10, 10)
- // 描边
- ctx.stroke()
- }
- /**
- * 等腰三角形 ,继续画解决锯齿
- * @param ctx
- */
- function b (ctx) {
- ctx.beginPath()
- ctx.moveTo(110, 10)
- ctx.lineTo(160, 60)
- /* 这些线条接着画不会出现锯齿*/
- ctx.lineTo(60, 60)
- ctx.lineTo(110, 10)
- // 解决锯齿
- ctx.lineTo(160, 60)
- /* 这里也要接下继续画取消底点锯齿*/
- // 线条颜色设置,必须放在绘制之前 ctx.strokeStyle = css任意的颜色表示
- ctx.strokeStyle = 'blue'
- // 线宽设置,必须放在绘制之前
- ctx.lineWidth = 6
- ctx.stroke()
- }
- /**
- * 闭合路径:
- * 从当前路径的起点点到结束点连一条路径。
- * ctx.closePath()
- * 图形可以省去最后一条边,也解决了锯齿
- * @param ctx
- */
- function c (ctx) {
- ctx.beginPath() // 清除当前路径,开启新路径,解决了所有图片颜色覆盖问题
- ctx.moveTo(110, 10)
- ctx.lineTo(160, 60)
- ctx.lineTo(60, 60)
- // 有了closePath,绘图直线图形时,最后一条边就可以省去了
- ctx.closePath()
- ctx.strokeStyle = 'yellow'
- // 线宽设置,必须放在绘制之前
- ctx.lineWidth = 6
- ctx.fillStyle = 'red' // 填充色
- ctx.fill() // 填充 默认黑色
- ctx.stroke()
- }
- /*
- * 非零环绕原则:
- * 是用来判断哪些区域属于路径内( 计算结果非0,即为路径内,有填充色 )。
- * 在路径包围的区域中,随便找一点,向外发射一条射线,
- * 和所有围绕它的边相交,
- * 然后开启一个计数器,从0计数,
- * 如果这个射线遇到顺时针围绕,那么+1,
- * 如果遇到逆时针围绕,那么-1,
- * 如果最终值非0,则这块区域在路径内。
- *
- * 备注:基数边的区域一定在路径内,有填充色。(画线过程体现出图形的方向)
- * */
- // 封装一个绘制矩形的函数
- function juXing (startX, startY, width, height, lineWidth, strokeStyle, fillStyle) {
- ctx.moveTo(startX, startY)
- ctx.lineTo(startX + width, startY)
- ctx.lineTo(startX + width, startY + height)
- ctx.lineTo(startX, startY + height)
- ctx.closePath()
- ctx.lineWidth = lineWidth
- ctx.strokeStyle = strokeStyle
- ctx.fillStyle = fillStyle
- /*
- * 描边的时候,会占用原图形的一部分( 线宽的一半 )。
- * 所以,日常开发中,为了让线宽符合要求,
- * 最好先填充,再描边,防止填充时覆盖掉线宽的一半。
- * */
- ctx.fill()
- ctx.stroke()
- }
- /**
- * 中间空的填充矩形
- * 两个矩形 一个逆时针画,一个顺时针画,
- * 最中间部分,根据非零环绕原则等于0,则是在路径外,无填充色
- * @param ctx
- */
- function middleEmpty (ctx) {
- // 顺时针画一个大矩形
- juXing(10, 10, 100, 100, 6, 'skyblue')
- // 逆时针画一个小矩形
- ctx.moveTo(35, 35)
- ctx.lineTo(35, 55)
- ctx.lineTo(55, 55)
- ctx.lineTo(55, 35)
- // 顺 -> 两个都是顺时针的话,全都被填充了
- /* ctx.moveTo( 35, 35 );
- ctx.lineTo( 55, 35 );
- ctx.lineTo( 55, 55 );
- ctx.lineTo( 35, 55 );*/
- ctx.lineWidth = 3
- ctx.strokeStyle = 'blue'
- ctx.closePath()
- ctx.stroke()
- // 一起填充
- ctx.fillStyle = 'red'
- ctx.fill()
- }
- </script>
- </body>
- </html>
2.canvas 线帽(线顶点)、线连接点、矩形api,清空画布,渐变矩形(一堆线加上 rgb线条颜色 )
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>canvas</title>
- </head>
- <style>
- canvas {
- border: 1px solid red;
- }
- p {
- border: 2px solid blue;
- padding:10px;
- margin-right: 10px;
- }
- </style>
- <body>
- <canvas id="can" width="300" height="300"></canvas>
- <div style="display: flex;">
- <p class="juxing">线帽(线顶点)lineCap</p>
- <p class="triangle">线连接点 lineJoin</p>
- <p class="triangle2">矩形api</p>
- <p class="middleEmpty">清空画布</p>
- <p class="bian">渐变矩形</p>
- </div>
- <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
- <script>
- let cvs = document.getElementById('can')
- let ctx = cvs.getContext('2d')
- $('.juxing').click(function () {
- a(ctx)
- })
- $('.triangle').click(function () {
- b(ctx)
- })
- $('.triangle2').click(function () {
- c(ctx)
- })
- $('.middleEmpty').click(function () {
- d(ctx, cvs)
- })
- $('.bian').click(function () {
- lineGarden(ctx)
- })
- /*
- * 设置线帽样式:
- * ctx.lineCap = ‘butt' 、'round'、'square'
- * butt是默认值,
- * round线头是圆的,多了两个半径出来,比默认的长
- * square线头两段各增加线宽的一半,比默认的长
- * */
- function a (ctx) {
- ctx.beginPath() // 防止 stroke 重绘之前的路径 默认 stroke 会生成所有路径
- // canvas在绘制线条的时候,会向左向右偏移线宽的一半,然后进行绘制。
- // 如果线宽为奇数,那么边缘的颜色值,会缩减一半(调整线条粗细看效果)。
- ctx.lineWidth = 10
- // 默认线头
- ctx.moveTo(10, 10)
- ctx.lineTo(210, 10)
- ctx.stroke()
- ctx.beginPath()
- ctx.lineCap = 'square' // 增长线头,两端各增长线宽的一半
- // ctx.lineCap = 'round'; // 圆线头,两端的圆半径为线宽的一半
- ctx.moveTo(10, 30)
- ctx.lineTo(210, 30)
- ctx.stroke()
- }
- /*
- * 设置线连接点样式:
- * ctx.lineJoin = ‘miter' 、'round'、'bevel'
- * miter是默认值,两边向外延伸相交为尖尖角,
- * round是圆头,
- * bevel两边相连为一个斜面。
- * */
- function b (ctx) {
- ctx.beginPath()
- ctx.lineWidth = 10
- // 默认交点为尖尖角
- ctx.lineJoin = 'miter'
- ctx.moveTo(10, 10)
- ctx.lineTo(60, 110)
- ctx.lineTo(110, 10)
- ctx.stroke()
- ctx.beginPath()
- ctx.lineJoin = 'round' // 交点为圆头
- // ctx.lineJoin = 'bevel'; // 交点为斜面
- ctx.moveTo(10, 50)
- ctx.lineTo(60, 150)
- ctx.lineTo(110, 50)
- ctx.stroke()
- }
- function c (ctx) {
- ctx.beginPath()
- /*
- * 画一个矩形路径:
- * ctx.rect( 起点x轴坐标,起点y轴坐标,宽,高 );
- * */
- ctx.rect(30, 10, 50, 50)
- ctx.stroke()
- /*
- * 绘制一个描边矩形,这个方法不会产生任何路径:
- * ctx.strokeRect( 起点x轴坐标,起点y轴坐标,宽,高 )
- * */
- ctx.strokeRect(30, 100, 50, 50)
- /*
- * 绘制一个填充矩形,这个方法不会产生任何路径:
- * ctx.fillRect( 起点x轴坐标,起点y轴坐标,宽,高 )
- * */
- ctx.fillRect(30, 170, 50, 50)
- }
- function d (ctx, cvs) {
- /*
- * 按照矩形的大小来清除画布中指定位置的内容:
- * ctx.clearRect( 起点x轴坐标,起点y轴坐标,宽,高 );
- * */
- ctx.clearRect(0, 0, cvs.width, cvs.height)
- }
- /* 渐变矩形 画一堆横线,加上rgb 线条*/
- function lineGarden (ctx) {
- // 需求,在50,50点绘制一个宽高各100的渐变矩形
- var i = 0, len = 100
- for (; i < len; i++) {
- // 为了防止重绘
- ctx.beginPath()
- ctx.moveTo(50, 50 + i)
- ctx.lineTo(150, 50 + i)
- // 红色通道值依次累加
- ctx.strokeStyle = 'rgb(' + 0 + ', ' + Math.floor(255 / 99 * i) + ', ' + 255 + ' )'
- // ctx.strokeStyle = 'rgb(' + 0 + ', ' + i + ', ' + 255 + ' )';
- ctx.stroke()
- }
- }
- </script>
- </body>
- </html>
3. canvas 折线图
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- <style>
- canvas {
- border: 1px solid red;
- }
- </style>
- </head>
- <body>
- 0.各部分都可单独研究绘画细节
- 1.定义坐标轴距离画布上下左右的边距
- 定义线条粗细
- 2.求横坐标原点,x轴顶点,y轴顶点坐标,并画x/y轴
- 3.定义箭头的宽高,把箭头当成一个矩形,放大可看细节,并填充
- 4.画任意点,把点当成矩形来画 fillRect() 宽高为2,为1的话颜色太浅, 宽高可以适当变大变小
- 5.画折线,连接的点实际上连接的是小矩形的左上角顶点,要偏移一下坐标,坐标偏移小矩形宽高的一半,使线穿过小矩形的中心
- 6.计算 x/y轴的长度,计算数据的缩放比例
- 7.[1,5640,654,2,2,6,5,3,56] 根据y轴的缩放比例来修改原数据,根据x轴的缩放比例来显示各个点的间距
- <canvas id="cvs" width="500" height="500"></canvas>
- <script>
- var cvs = document.getElementById('cvs');
- var ctx = cvs.getContext('2d');
- ctx.lineWidth = 2;
- // 坐标轴距离画布上右下左的边距
- var padding = {
- top: 20,
- right: 20,
- bottom: 20,
- left: 20
- }
- // 坐标轴中箭头的宽和高
- var arrow = {
- width: 12,
- height: 20
- }
- // 求坐标轴上顶点的坐标
- var vertexTop = {
- x: padding.left,
- y: padding.top
- }
- // 求坐标轴原点的坐标
- var origin = {
- x: padding.left,
- y: cvs.height - padding.bottom
- }
- // 求坐标轴右顶点的坐标
- var vertexRight = {
- x: cvs.width - padding.right,
- y: cvs.height - padding.bottom
- }
- // 画坐标轴中的两条线
- ctx.moveTo( vertexTop.x, vertexTop.y );
- ctx.lineTo( origin.x, origin.y );
- ctx.lineTo( vertexRight.x, vertexRight.y );
- ctx.stroke();
- // 画上顶点箭头
- ctx.beginPath();
- ctx.moveTo( vertexTop.x, vertexTop.y );
- ctx.lineTo( vertexTop.x - arrow.width / 2, vertexTop.y + arrow.height );
- ctx.lineTo( vertexTop.x, vertexTop.y + arrow.height / 2 );
- ctx.lineTo( vertexTop.x + arrow.width / 2, vertexTop.y + arrow.height );
- ctx.closePath();
- ctx.fill();
- // 画右顶点箭头
- ctx.beginPath();
- ctx.moveTo( vertexRight.x, vertexRight.y );
- ctx.lineTo( vertexRight.x - arrow.height, vertexRight.y - arrow.width / 2 );
- ctx.lineTo( vertexRight.x - arrow.height / 2, vertexRight.y );
- ctx.lineTo( vertexRight.x - arrow.height, vertexRight.y + arrow.width / 2 );
- ctx.closePath();
- ctx.fill();
- // 求坐标轴默认可显示数据的最大值
- coordMaxX = cvs.width - padding.left - padding.right - arrow.height;
- coordMaxY = cvs.height - padding.top - padding.bottom - arrow.height;
- /*
- * 在坐标轴中指定位置画点,坐标算法:
- * 点的x轴:原点x坐标 + 点到原点的水平距离
- * 点的y轴:原点y坐标 - 点到原点的垂直距离
- * */
- // 需求,利用折线图的方式展示一下门口大爷酱香饼每日销售量
- // [ 10, 20, 50, 80, 120, 300, 100, 50, 2 ];
- var data = [ 100, 200, 400, 600, 1200, 1800, 1000, 500, 20 ];
- // 求数据缩放的比例
- var ratioX = coordMaxX / data.length;
- var ratioY = coordMaxY / Math.max.apply( null, data );
- // 根据比例,对元数据进行缩放
- var ratioData = data.map( function( val, i ) {
- return val * ratioY;
- });
- // 画点
- ratioData.forEach( function( val, index ) {
- ctx.fillRect( origin.x + ( index * ratioX) - 2, origin.y - val - 2, 4, 4 );
- });
- // 画折线
- ctx.beginPath();
- ratioData.forEach( function( val, index ) {
- ctx.lineTo( origin.x + ( index * ratioX), origin.y - val );
- });
- ctx.stroke();
- </script>
- </body>
- </html>
4. canvas 饼图
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- <style>
- canvas {
- border: 1px solid red;
- }
- p{
- line-height: 30px;
- margin:0;
- }
- </style>
- </head>
- <body>
- <p>混入式继承,换种方式的原型继续 Person.prototype={}</p>
- 画扇形 <br/>
- <p>1.计算数据占的比例 i/sum*360度</p>
- <p>2. 度数转为弧度</p>
- <p>3.每一个扇形的开始弧度等于上一个扇形的结束弧度
- 每一个扇形的结束弧度等于上一个扇形的结束弧度+所占的弧度</p>
- <p>4. 画扇形 填充</p>
- <p>5.0计算扇形平分线的坐标(即圆上点的坐标)</p>
- <p>5.1画平分线,并延长(延长半径,则平分钱也延长了)并填充颜色,覆盖点扇形内的线</p>
- <p>6绘制文字</p>
- <canvas id="cvs" width="500" height="500"></canvas>
- <script>
- (function (w) {
- // 把角度转换为弧度
- function angleToRadian (angle) {
- return Math.PI / 180 * angle
- }
- // 混入式继承
- function extend (o1, o2) {
- for (var key in o2) {
- // 只有o2自己的属性才会copy到o1身上
- if (o2.hasOwnProperty(key)) {
- o1[key] = o2[key]
- }
- }
- }
- /*
- * constrcutor { Pipe } 饼图构造函数
- * param { x: number } 圆心x轴坐标
- * param { y: number } 圆心y轴坐标
- * param { r: number } 圆半径
- * param { data: Array } 绘制饼图所需的数据
- * */
- function Pipe (x, y, r, data) {
- this.x = x
- this.y = y
- this.r = r
- this.data = data
- // 一组颜色
- this.colors = ['orange', 'orchid', 'palegoldenrod', 'palegreen', 'paleturquoise', 'peru', 'pink']
- }
- // 给原型扩充方法
- extend(Pipe.prototype, {
- // 绘制饼图
- draw: function () {
- // 在外面保存一下this
- var self = this
- // 数据的总和
- var num = 0
- this.data.forEach(function (obj) {
- num += obj.val
- })
- // 一个数据值所占用的角度
- var baseAngle = 360 / num
- // 假设一开始就绘制了一个起始为0,结束为0的扇形
- var startAngle = 0,
- endAngle = 0,
- lineAngle = 0,
- lineX, lineY
- // 画扇形
- this.data.forEach(function (obj, i) {
- // 每次进来,计算当前扇形的起始角度和结束角度
- // 下一个扇形的起始角度,是当前扇形的结束角度
- startAngle = endAngle
- // 这个结束角度 = 上一个扇形的结束角度 + 当前数值所对应的角度
- endAngle = endAngle + baseAngle * obj.val
- // 求扇形中间线的角度
- lineAngle = startAngle + baseAngle * obj.val / 2;
- /*
- * 根据中间线的角度,求中间的线的x和y坐标:
- * x = 圆心x + r * Math.cos( angleToRadian( pointAngle ) )
- * y = 圆心y + r * Math.sin( angleToRadian( pointAngle ) )
- * */
- lineX = self.x + ( self.r + 20 ) * Math.cos( angleToRadian( lineAngle ) );
- lineY = self.y + ( self.r + 20 ) * Math.sin( angleToRadian( lineAngle ) );
- // 第一个扇形
- ctx.beginPath()
- ctx.moveTo(self.x, self.y)
- ctx.arc(self.x, self.y, self.r, angleToRadian(startAngle), angleToRadian(endAngle))
- ctx.closePath()
- ctx.fillStyle = self.colors[i]
- ctx.fill()
- // 画每一个扇形的平分线
- ctx.beginPath();
- ctx.moveTo( self.x, self.y );
- ctx.lineTo( lineX, lineY );
- ctx.strokeStyle = self.colors[ i ];
- ctx.stroke();
- // 绘制文字
- if ( lineAngle >= 90 && lineAngle <= 270 ) {
- ctx.textAlign = 'right';
- }else {
- ctx.textAlign = 'left';
- }
- ctx.fillText( obj.msg, lineX, lineY );
- })
- }
- })
- // 把构造函数暴露到全局
- w.Pipe = Pipe
- }(window));
- var cvs = document.getElementById('cvs')
- var ctx = cvs.getContext('2d')
- // var pipe = new Pipe( 200, 200, 80, [ 10, 30, 50, 60, 20 ] );
- // [ 10, 30, 50, 60, 20 ]
- var pipe = new Pipe(200, 200, 80, [
- {
- val: 10,
- msg: '米饭'
- },
- {
- val: 30,
- msg: '面条'
- },
- {
- val: 50,
- msg: '馒头'
- },
- {
- val: 50,
- msg: '豆腐脑'
- },
- {
- val: 50,
- msg: '饺子'
- },
- {
- val: 90,
- msg: '汤圆'
- },
- ])
- pipe.draw()
- </script>
- </body>
- </html>
5.canvas 生成图片、画弧、扇形、文字
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>canvas</title>
- </head>
- <style>
- canvas {
- border: 1px solid red;
- }
- p {
- border: 2px solid blue;
- padding: 10px;
- margin-right: 10px;
- }
- </style>
- <body>
- <canvas id="can" width="300" height="300"></canvas>
- <div style="display: flex;">
- <p class="juxing">虚线 setLineDash 生成图片 canvas.toDataUrl('image/png')</p>
- <p class="triangle">画弧</p>
- <p class="triangle2">扇形</p>
- <p class="middleEmpty">清空画布</p>
- <p class="bian">文字</p>
- </div>
- <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
- <script>
- let cvs = document.getElementById('can')
- let ctx = cvs.getContext('2d')
- $('.juxing').click(function () {
- a(ctx, cvs)
- })
- $('.triangle').click(function () {
- b(ctx)
- })
- $('.triangle2').click(function () {
- c(ctx)
- })
- $('.middleEmpty').click(function () {
- d(ctx, cvs)
- })
- $('.bian').click(function () {
- e(ctx)
- })
- /*
- * 设置画线的时候空白部分和实线部分的大小。
- * ctx.setLineDash( [ 5, 3 ] )
- * 参数可以任意多个
- * */
- function a (ctx, cvs) {
- ctx.beginPath()
- ctx.lineDashOffset = 3 // 设置偏移量,进行微调用,效果不明显
- ctx.setLineDash([5, 3]) // 5像素实线,3像素空白,则变成了虚线
- ctx.moveTo(10, 10)
- ctx.lineTo(210, 10)
- ctx.stroke()
- let url = cvs.toDataURL('image/png')
- let img = document.createElement('img')
- img.src = url
- document.body.appendChild(img)
- /*
- * 获取线条绘制规则。
- * ctx.getLineDash()
- * */
- console.log(ctx.getLineDash())
- }
- /*
- * 画弧( 画的是路径 )
- * ctx.arc( 圆心x轴坐标,圆心y轴坐标,半径, 起点弧度,结束点弧度,是否逆时针画(可选) )
- * arc方法内部会先从路径结束点到弧的起点画一条路径线。
- * 起点弧度、结束点弧度以及弧度的方向共同决定了弧的大小。
- * */
- // 把角度转换为弧度
- function angleToRadian (angle) {
- return Math.PI / 180 * angle
- }
- function b (ctx) {
- ctx.beginPath()
- // 顺时针画一段弧 从x轴水平线右侧开始 默认顺时针
- ctx.arc(100, 100, 30, angleToRadian(90), angleToRadian(270))
- ctx.stroke()
- // 逆时针画一段弧
- ctx.beginPath()
- ctx.arc(200, 100, 30, angleToRadian(90), angleToRadian(270), true)
- ctx.stroke()
- }
- function c (ctx) {
- ctx.beginPath()
- /*
- * 画扇形:
- * 1、先设置路径起点为圆心
- * 2、画弧
- * 3、闭合路径
- * */
- ctx.beginPath()
- ctx.moveTo(100, 100) // arc方法内部会先从路径结束点到弧的起点画一条路径线。
- ctx.arc(100, 100, 90, angleToRadian(220), angleToRadian(310))
- ctx.closePath()
- ctx.stroke()
- }
- function d (ctx, cvs) {
- ctx.clearRect(0, 0, cvs.width, cvs.height)
- ctx.setLineDash([]) // 清空虚线
- }
- /*
- * 设置文字的属性
- * ctx.font = 和css语法一样。
- * 注意:这里设置字体大小时必须带单位,单位支持css的所有表示方式。
- * 注意:单独设置字体大小不会生效,必须要加一个额外属性样式。
- ctx.strokeText( 描边文字, 参考x轴坐标,参考y轴坐标,限制文字的最大长度(可选) )
- ctx.fillText( 填充文字, 参考x轴坐标,参考y轴坐标,限制文字的最大长度(可选) )
- * 设置文字的水平对其方式:
- * ctx.textAlign = 'left || start' 、 'right || end' 、 'center'
- * 默认值为start。
- * 设置文字的垂直对其方式:
- * ctx.textBaseline = 'top' 、'bottom'、'middle'、'alphabetic'、'hanging'、'ideographic'
- * 默认值为alphabetic。
- * */
- function e (ctx) {
- ctx.beginPath()
- // ctx.font = '3rem 微软雅黑'
- ctx.font = '28px 微软雅黑'
- ctx.fillStyle = 'deeppink';
- ctx.textAlign = 'left' // 水平对齐
- ctx.textBaseline = 'middle' // 垂直对齐
- ctx.strokeText('描边字', 100, 100) // 描边文字,空心字
- // ctx.strokeText('中文字',100,100,100) // 第一个参数限制文字宽度,小了则压缩字体
- ctx.fillText('中文字', 200, 200) // 填充文字,一般字
- // 绘制文字的参考点
- ctx.beginPath()
- ctx.arc(100, 100, 4, 0, Math.PI * 2)
- ctx.fill()
- // 在画布的左上角绘制一段文字
- ctx.textAlign = 'left';
- ctx.textBaseline = 'top';
- ctx.fillText( '左上角', 0, 0 );
- // 在画布的右上角绘制一段文字
- ctx.textAlign = 'right';
- ctx.textBaseline = 'top';
- ctx.fillText( '右上角', cvs.width, 0 );
- }
- </script>
- </body>
- </html>
6. canvas drawImage() 三参数、五参数、九参数、
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>canvas</title>
- </head>
- <style>
- canvas {
- border: 1px solid red;
- }
- </style>
- <body>
- <img src="NPC5.png" alt="" id="img"> <!-- 160*260 -->
- <canvas id="can" width="300" height="360"></canvas>
- <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
- <script>
- let cvs = document.getElementById('can')
- let ctx = cvs.getContext('2d')
- // 直接画,避开函数调用产生的异步问题
- /*
- * ctx.drawImage()
- * 绘制图像,有三种使用方式。
- * 三参数 图像、坐标x,坐标y
- * 五参数 图像、坐标x,坐标y, 图片宽,图片高
- * 九参数 把裁剪到的部分图像绘制到指定的坐标,并指定其大小。
- * drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh)
- * sx, sy, sw, sh 切原图一小块的坐标宽高
- * dx,dy,dw,dh 是最终图片的坐标,宽高
- * */
- let img = document.getElementById('img')
- img.onload = function () {
- // ctx.drawImage(img, 10, 10)
- // ctx.drawImage(img, 10, 100, img.width, img.height)
- // drawImage(image, dx, dy)
- // drawImage(image, dx, dy, dw, dh)
- // drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh)
- ctx.drawImage(img, 0, img.height / 4 * 2, img.width / 4, img.height / 4,
- 40, 140, img.width / 4, img.height / 4)
- let i = 0, step = 0
- let interval = setInterval(() => {
- ctx.clearRect(80, 140, cvs.width, cvs.height)
- ctx.drawImage(img, img.width / 4 * i, img.height / 4, img.width / 4, img.height / 4,
- 180 - step * 5, 140, img.width / 4, img.height / 4)
- i++
- step++
- if (i > 3) {
- i = 0
- }
- if (180 - step * 5 < 80) {
- window.clearInterval(interval)
- }
- }, 100)
- }
- </script>
- </body>
- </html>
7.canvas 平移 translate、旋转 rotate、缩放 scale
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- <style>
- canvas {
- border: 1px solid red;
- }
- </style>
- </head>
- <body>
- <canvas width="300" height="300" id="can"></canvas>
- <script>
- let cvs = document.getElementById('can')
- let ctx = cvs.getContext('2d')
- /*
- * 平移,移动原来的矩形
- * 平移、缩放、旋转会叠加
- * */
- ctx.fillRect(30, 30, 20, 20)
- ctx.translate(20, 20)
- ctx.fillStyle = 'blue'
- ctx.fillRect(30, 30, 20, 20)
- /*
- * 旋转 相对于原点的旋转
- * 先平移到中间某位置
- * */
- ctx.translate(100, 100)
- ctx.fillRect(0, 0, 30, 30) // 从 (0,0)开始
- ctx.rotate(Math.PI / 6)
- ctx.fillStyle = 'red'
- ctx.fillRect(0, 0, 30, 30)
- ctx.rotate(Math.PI / 6)
- ctx.fillStyle = 'pink'
- ctx.fillRect(0, 0, 30, 30)
- /*
- * 缩放 相对于原点的缩放
- * 先平移到中间某位置
- * 最好单独试,免得叠加计算出错
- *
- * */
- ctx.rotate(-Math.PI / 6*2) // 旋转回来
- ctx.translate(60, 60)
- ctx.fillRect(0, 0, 40, 40)
- ctx.scale(0.5, 0.5)
- ctx.fillStyle = 'blue'
- ctx.fillRect(0, 0, 40, 40)
- </script>
- </body>
- </html>
8.工厂模式 函数返回时 return new Person(name,age)
- /* 工厂模式 */
- function Person (name, age) {
- this.name = name
- this.age = age
- }
- // 工厂
- // 工厂模式相当于省去new关键字
- function getPerson (name, age) {
- return new Person(name, age)
- }
- console.log(getPerson('女神', 18))
9.状态保存、回滚 ctx.save() ctx.restore() 判断点在画布中, 旋转图形绘制(第9不太懂)
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>canvas</title>
- </head>
- <style>
- canvas {
- border: 1px solid red;
- }
- p {
- border: 2px solid blue;
- padding: 10px;
- margin-right: 10px;
- }
- </style>
- <body>
- <canvas id="can" width="300" height="360"></canvas>
- <div style="display: flex;">
- <p class="juxing">状态保存、回滚 ctx.save() restore()</p>
- <p class="triangle">判断点在画布中</p>
- </div>
- <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
- <script>
- let cvs = document.getElementById('can')
- let ctx = cvs.getContext('2d')
- /*
- * 绘制一个旋转图形的步骤:
- * 1、先平移坐标轴到图形的中心
- * 2、旋转坐标轴
- * 3、绘制图形( 需要注意,平移旋转之后,坐标体系变化,不能按照之前定好的坐标来绘制旋转图形 )
- * */
- /* // 正常情况下的参考矩形
- ctx.fillStyle = 'pink';
- ctx.fillRect( 100, 100, 50, 50 ); // 原来的图形
- // 平移到矩形的中心
- ctx.translate( 125, 125 );
- // 旋转坐标系
- ctx.rotate( Math.PI / 180 * 30 );
- // 绘制图形
- ctx.fillStyle = 'blue';
- ctx.fillRect( -25, -25, 50, 50 ); // 新坐标为宽高的一半,不懂。*/
- // 定时器
- // 先统一平移到矩形的中心
- ctx.translate(125, 125)
- // 基于这个中心不断绘制旋转矩形
- setInterval(function () {
- // 清除上一次的矩形
- ctx.clearRect(-50, -50, cvs.width, cvs.height)
- // 旋转坐标系
- ctx.rotate(Math.PI / 180 * 4)
- // 绘制图形
- ctx.fillRect(-25, -25, 50, 50)
- }, 50)
- /* 工厂模式 */
- function Person (name, age) {
- this.name = name
- this.age = age
- }
- // 工厂
- // 工厂模式相当于省去new关键字
- function getPerson (name, age) {
- return new Person(name, age)
- }
- console.log(getPerson('女神', 18))
- /**
- * 状态保存: ctx.save();
- * 状态回滚: ctx.restore();
- * */
- $('.juxing').click(function () {
- // 保存下面的状态
- ctx.save()
- ctx.lineWidth = 10
- ctx.strokeStyle = 'blue'
- ctx.moveTo(10, 10)
- ctx.lineTo(210, 10)
- ctx.stroke()
- // 再保存下面的状态
- ctx.save()
- ctx.strokeStyle = 'green'
- ctx.beginPath()
- ctx.moveTo(10, 60)
- ctx.lineTo(210, 60)
- ctx.stroke()
- // 回滚
- ctx.restore()
- ctx.beginPath()
- ctx.moveTo(10, 90)
- ctx.lineTo(210, 90)
- ctx.stroke()
- })
- $('.triangle').click(function () {
- /*
- * 判断点在不在路径中:
- * ctx.isPointInPath( 要判断的点x轴坐标,要判断的点y轴坐标 )
- * */
- ctx.rect(10, 10, 50, 50)
- ctx.stroke()
- // 点击画布,判断点击的位置在不在路径中
- cvs.addEventListener('click', function (e) {
- var x = e.pageX - cvs.offsetLeft
- var y = e.pageY - cvs.offsetTop
- alert(ctx.isPointInPath(x, y))
- })
- })
- </script>
- </body>
- </html>
10 监听者模式(不懂)
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- </head>
- <body>
- <script>
- // 一个监听者 服务与 多个听众
- // 监听者
- var jianTingZhe = {
- // 听众列表
- listeners: {
- birdOver: [],
- birdFlappy: [],
- birdRotate: []
- },
- // 小鸟死亡触发时,告知所有监听死亡的听众
- triggerBirdOver: function() {
- this.listeners.birdOver.forEach( function( listen ) {
- listen();
- });
- },
- // 小鸟飞翔的时候,告知所有监听飞翔的听众
- triggerBirdFlappy: function() {
- this.listeners.birdFlappy.forEach( function( listen ) {
- listen();
- });
- },
- // 小鸟飞翔的时候,告知所有监听飞翔的听众
- triggerBirdRotate: function() {
- this.listeners.birdRotate.forEach( function( listen ) {
- listen();
- });
- }
- };
- // 这是一个模块,整体可以认为是一个听众监听N多事件
- (function( w ) {
- // 小鸟死亡听众
- jianTingZhe.listeners.birdOver.push( function() {
- console.log( '小鸟死了,我就哭' );
- } );
- jianTingZhe.listeners.birdOver.push( function() {
- console.log( '小鸟死了,我很伤心' );
- } );
- jianTingZhe.listeners.birdOver.push( function() {
- console.log( '小鸟死了,我要埋葬它' );
- } );
- // 小鸟飞翔听众
- jianTingZhe.listeners.birdFlappy.push( function() {
- console.log( '小鸟飞了,我很搞笑' );
- });
- jianTingZhe.listeners.birdFlappy.push( function() {
- console.log( '小鸟飞了,我要把射下来' );
- });
- // 小鸟旋转听众
- jianTingZhe.listeners.birdRotate.push( function() {
- console.log( '小鸟转了,呱唧呱唧!' );
- });
- }( window ));
- // 这是另一个模块,整体可以认为是一个听众
- (function( w ) {
- // 小鸟旋转听众
- jianTingZhe.listeners.birdRotate.push( function() {
- console.log( '我是模块2' );
- });
- }( window ));
- // 监听到小鸟死了
- jianTingZhe.triggerBirdOver();
- // 监听到小鸟转了
- jianTingZhe.triggerBirdRotate()
- // 监听到小鸟飞翔了
- jianTingZhe.triggerBirdFlappy()
- </script>
- </body>
- </html>
11.动画帧函数 requestAnimationFrame 函数回调的触发是由浏览器来控制的,行就会比较稳定,适合用来做流畅的动画。
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- <style>
- div {
- height: 20px;
- background-color: black;
- }
- </style>
- </head>
- <body>
- <div id="div"></div>
- <script>
- /*
- * 请求动画帧函数,这个函数和setTimeout方法使用类似,
- * 他都是定时器,却别在于setTimeout可以自由指定回调的触发时间,
- * 而requestAnimationFrame函数回调的触发是由浏览器来控制的。
- *
- * requestAnimationFrame( callback )
- * 备注:当浏览器重绘页面的时候,就会调用这个callback,
- * 这样callbackg的执行就会比较稳定,适合用来做流畅的动画。
- * */
- /*setInterval( function() {
- console.log(111);
- }, 50);*/
- /*function con() {
- console.log(111);
- setTimeout( con, 50);
- }
- setTimeout( con, 50);*/
- // 简化setTimeout不断执行回调的方式
- /*(function con() {
- console.log(111);
- setTimeout( con, 50);
- }());*/
- // 把setTimeout改为requestAnimationFrame
- (function con() {
- console.log(111);
- requestAnimationFrame( con );
- }());
- </script>
- </body>
- </html>
12. ctx2.drawImage( cvs1, 0, 0 ); // 把第一个canvas的内容绘制到第二个canvas中
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- <style>
- div {
- height: 20px;
- background-color: black;
- }
- </style>
- </head>
- <body>
- <canvas id="cvs1"></canvas>
- <canvas id="cvs2"></canvas>
- <script>
- /*
- * drawImage的第一个参数可以是img、canvas或video
- * */
- var cvs1 = document.querySelector( '#cvs1' );
- var cvs2 = document.querySelector( '#cvs2' );
- var ctx1 = cvs1.getContext( '2d' );
- var ctx2 = cvs2.getContext( '2d' );
- // 给第一个画布绘制内容
- ctx1.fillRect( 10, 10, 100, 100 );
- // 把第一个canvas的内容绘制到第二个canvas中
- ctx2.drawImage( cvs1, 0, 0 );
- ctx2.fillStyle = 'blue';
- ctx2.fillRect( 0, 0, 50, 50 );
- </script>
- </body>
- </html>
canvas20181114的更多相关文章
随机推荐
- bash中打印文件每一行及其行号
#!/bin/bash linenumber=$(cat remoteIP.cfg |wc -l) currentline= for ip in $(cat remoteIP.cfg) do curr ...
- spring 中的设计模式
https://mp.weixin.qq.com/s?__biz=MzU0MDEwMjgwNA==&mid=2247485205&idx=1&sn=63455d2313776d ...
- Android studio Error: Modules no specified解决和真机调试
如何配置SDK百度一大堆: 前言:Android Studio很完善,如果SDK配置好,理论上就是 创建项目->创建个APP(名字自己随便起)->打开手机开发者模式运行即可:如果出了问题, ...
- HTTP协议6之状态码--转
HTTP状态码,我都是现查现用. 我以前记得几个常用的状态码,比如200,302,304,404, 503. 一般来说我也只需要了解这些常用的状态码就可以了. 如果是做AJAX,REST,网络爬虫, ...
- 二叉树(BT)相关
1.same tree /** * Definition for binary tree * public class TreeNode { * int val; * TreeNode left; * ...
- SQL判断语句
,,decode(tts.execute_state,,'false','true')) from twf_tech_schedule tts sql判断语句
- 20155324《网络对抗》Exp1 PC平台逆向破解(5)M
20155324<网络对抗>Exp1 PC平台逆向破解(5)M 实验目标 本次实践的对象是一个名为~pwn1~的~linux~可执行文件. 该程序正常执行流程是:~main~调用~foo~ ...
- 【2】学习C++之引用
C++中的引用类似于现实生活中人们之间起昵称,昵称和本名都可以辨别人. 1.普通变量的引用: ;//a为本名 int &b=a;//b为a的昵称 其中不能光有昵称没有本名,如果只定义了引用,却 ...
- 20175306 迭代和JDB调试
迭代和JDB调试 1.使用C(n,m)=C(n-1,m-1)+C(n-1,m)公式进行递归编程实现求组合数C(m,n)的功能 代码展示: public class C { public static ...
- 自己写的一个用js把select换成div与span与ul的东西
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...