1. canvas 描边、填充、画线、闭合路径、非零环绕原则

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>canvas</title>
  6. </head>
  7. <style>
  8. canvas {
  9. border: 1px solid red;
  10. }
  11. </style>
  12. <body>
  13. <canvas id="can" width="300" height="300"></canvas>
  14. <p class="juxing">矩形</p>
  15. <p class="triangle">三角形锯齿问题</p>
  16. <p class="triangle2">三角形闭合没锯齿,填充色</p>
  17. <p class="middleEmpty">中空矩形</p>
  18. <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
  19. <script>
  20. let cvs = document.getElementById('can')
  21. let ctx = cvs.getContext('2d')
  22. $('.juxing').click(function () {
  23. a(ctx)
  24. })
  25. $('.triangle').click(function () {
  26. b(ctx)
  27. })
  28. $('.triangle2').click(function () {
  29. c(ctx)
  30. })
  31. $('.middleEmpty').click(function () {
  32. middleEmpty(ctx)
  33. })
  34.  
  35. /**
  36. * 矩形
  37. * @param ctx
  38. */
  39. function a (ctx) {
  40. ctx.beginPath()
  41. // 初始位置
  42. ctx.moveTo(10, 10)
  43. // 线条
  44. ctx.lineTo(110, 10)
  45. ctx.lineTo(110, 110)
  46. ctx.lineTo(10, 110)
  47. ctx.lineTo(10, 10)
  48. // 描边
  49. ctx.stroke()
  50. }
  51.  
  52. /**
  53. * 等腰三角形 ,继续画解决锯齿
  54. * @param ctx
  55. */
  56. function b (ctx) {
  57. ctx.beginPath()
  58. ctx.moveTo(110, 10)
  59.  
  60. ctx.lineTo(160, 60)
  61. /* 这些线条接着画不会出现锯齿*/
  62. ctx.lineTo(60, 60)
  63. ctx.lineTo(110, 10)
  64.  
  65. // 解决锯齿
  66. ctx.lineTo(160, 60)
  67. /* 这里也要接下继续画取消底点锯齿*/
  68.  
  69. // 线条颜色设置,必须放在绘制之前 ctx.strokeStyle = css任意的颜色表示
  70. ctx.strokeStyle = 'blue'
  71. // 线宽设置,必须放在绘制之前
  72. ctx.lineWidth = 6
  73.  
  74. ctx.stroke()
  75. }
  76.  
  77. /**
  78. * 闭合路径:
  79. * 从当前路径的起点点到结束点连一条路径。
  80. * ctx.closePath()
  81. * 图形可以省去最后一条边,也解决了锯齿
  82. * @param ctx
  83. */
  84. function c (ctx) {
  85. ctx.beginPath() // 清除当前路径,开启新路径,解决了所有图片颜色覆盖问题
  86. ctx.moveTo(110, 10)
  87. ctx.lineTo(160, 60)
  88. ctx.lineTo(60, 60)
  89. // 有了closePath,绘图直线图形时,最后一条边就可以省去了
  90. ctx.closePath()
  91.  
  92. ctx.strokeStyle = 'yellow'
  93. // 线宽设置,必须放在绘制之前
  94. ctx.lineWidth = 6
  95. ctx.fillStyle = 'red' // 填充色
  96. ctx.fill() // 填充 默认黑色
  97. ctx.stroke()
  98. }
  99.  
  100. /*
  101. * 非零环绕原则:
  102. * 是用来判断哪些区域属于路径内( 计算结果非0,即为路径内,有填充色 )。
  103. * 在路径包围的区域中,随便找一点,向外发射一条射线,
  104. * 和所有围绕它的边相交,
  105. * 然后开启一个计数器,从0计数,
  106. * 如果这个射线遇到顺时针围绕,那么+1,
  107. * 如果遇到逆时针围绕,那么-1,
  108. * 如果最终值非0,则这块区域在路径内。
  109. *
  110. * 备注:基数边的区域一定在路径内,有填充色。(画线过程体现出图形的方向)
  111. * */
  112.  
  113. // 封装一个绘制矩形的函数
  114. function juXing (startX, startY, width, height, lineWidth, strokeStyle, fillStyle) {
  115.  
  116. ctx.moveTo(startX, startY)
  117. ctx.lineTo(startX + width, startY)
  118. ctx.lineTo(startX + width, startY + height)
  119. ctx.lineTo(startX, startY + height)
  120. ctx.closePath()
  121.  
  122. ctx.lineWidth = lineWidth
  123. ctx.strokeStyle = strokeStyle
  124. ctx.fillStyle = fillStyle
  125.  
  126. /*
  127. * 描边的时候,会占用原图形的一部分( 线宽的一半 )。
  128. * 所以,日常开发中,为了让线宽符合要求,
  129. * 最好先填充,再描边,防止填充时覆盖掉线宽的一半。
  130. * */
  131.  
  132. ctx.fill()
  133. ctx.stroke()
  134. }
  135.  
  136. /**
  137. * 中间空的填充矩形
  138. * 两个矩形 一个逆时针画,一个顺时针画,
  139. * 最中间部分,根据非零环绕原则等于0,则是在路径外,无填充色
  140. * @param ctx
  141. */
  142. function middleEmpty (ctx) {
  143. // 顺时针画一个大矩形
  144. juXing(10, 10, 100, 100, 6, 'skyblue')
  145.  
  146. // 逆时针画一个小矩形
  147. ctx.moveTo(35, 35)
  148. ctx.lineTo(35, 55)
  149. ctx.lineTo(55, 55)
  150. ctx.lineTo(55, 35)
  151. // 顺 -> 两个都是顺时针的话,全都被填充了
  152. /* ctx.moveTo( 35, 35 );
  153. ctx.lineTo( 55, 35 );
  154. ctx.lineTo( 55, 55 );
  155. ctx.lineTo( 35, 55 );*/
  156. ctx.lineWidth = 3
  157. ctx.strokeStyle = 'blue'
  158. ctx.closePath()
  159. ctx.stroke()
  160.  
  161. // 一起填充
  162. ctx.fillStyle = 'red'
  163. ctx.fill()
  164. }
  165.  
  166. </script>
  167. </body>
  168. </html>

2.canvas 线帽(线顶点)、线连接点、矩形api,清空画布,渐变矩形(一堆线加上 rgb线条颜色 )

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>canvas</title>
  6. </head>
  7. <style>
  8. canvas {
  9. border: 1px solid red;
  10. }
  11.  
  12. p {
  13. border: 2px solid blue;
  14. padding:10px;
  15. margin-right: 10px;
  16. }
  17. </style>
  18. <body>
  19. <canvas id="can" width="300" height="300"></canvas>
  20. <div style="display: flex;">
  21. <p class="juxing">线帽(线顶点)lineCap</p>
  22. <p class="triangle">线连接点 lineJoin</p>
  23. <p class="triangle2">矩形api</p>
  24. <p class="middleEmpty">清空画布</p>
  25. <p class="bian">渐变矩形</p>
  26. </div>
  27. <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
  28. <script>
  29. let cvs = document.getElementById('can')
  30. let ctx = cvs.getContext('2d')
  31. $('.juxing').click(function () {
  32. a(ctx)
  33. })
  34. $('.triangle').click(function () {
  35. b(ctx)
  36. })
  37. $('.triangle2').click(function () {
  38. c(ctx)
  39. })
  40. $('.middleEmpty').click(function () {
  41. d(ctx, cvs)
  42. })
  43. $('.bian').click(function () {
  44. lineGarden(ctx)
  45. })
  46.  
  47. /*
  48. * 设置线帽样式:
  49. * ctx.lineCap = ‘butt' 、'round'、'square'
  50. * butt是默认值,
  51. * round线头是圆的,多了两个半径出来,比默认的长
  52. * square线头两段各增加线宽的一半,比默认的长
  53. * */
  54.  
  55. function a (ctx) {
  56.  
  57. ctx.beginPath() // 防止 stroke 重绘之前的路径 默认 stroke 会生成所有路径
  58. // canvas在绘制线条的时候,会向左向右偏移线宽的一半,然后进行绘制。
  59. // 如果线宽为奇数,那么边缘的颜色值,会缩减一半(调整线条粗细看效果)。
  60. ctx.lineWidth = 10
  61.  
  62. // 默认线头
  63. ctx.moveTo(10, 10)
  64. ctx.lineTo(210, 10)
  65. ctx.stroke()
  66.  
  67. ctx.beginPath()
  68. ctx.lineCap = 'square' // 增长线头,两端各增长线宽的一半
  69. // ctx.lineCap = 'round'; // 圆线头,两端的圆半径为线宽的一半
  70. ctx.moveTo(10, 30)
  71. ctx.lineTo(210, 30)
  72. ctx.stroke()
  73. }
  74.  
  75. /*
  76. * 设置线连接点样式:
  77. * ctx.lineJoin = ‘miter' 、'round'、'bevel'
  78. * miter是默认值,两边向外延伸相交为尖尖角,
  79. * round是圆头,
  80. * bevel两边相连为一个斜面。
  81. * */
  82. function b (ctx) {
  83. ctx.beginPath()
  84. ctx.lineWidth = 10
  85.  
  86. // 默认交点为尖尖角
  87. ctx.lineJoin = 'miter'
  88. ctx.moveTo(10, 10)
  89. ctx.lineTo(60, 110)
  90. ctx.lineTo(110, 10)
  91. ctx.stroke()
  92.  
  93. ctx.beginPath()
  94. ctx.lineJoin = 'round' // 交点为圆头
  95. // ctx.lineJoin = 'bevel'; // 交点为斜面
  96. ctx.moveTo(10, 50)
  97. ctx.lineTo(60, 150)
  98. ctx.lineTo(110, 50)
  99. ctx.stroke()
  100.  
  101. }
  102.  
  103. function c (ctx) {
  104. ctx.beginPath()
  105. /*
  106. * 画一个矩形路径:
  107. * ctx.rect( 起点x轴坐标,起点y轴坐标,宽,高 );
  108. * */
  109. ctx.rect(30, 10, 50, 50)
  110. ctx.stroke()
  111.  
  112. /*
  113. * 绘制一个描边矩形,这个方法不会产生任何路径:
  114. * ctx.strokeRect( 起点x轴坐标,起点y轴坐标,宽,高 )
  115. * */
  116. ctx.strokeRect(30, 100, 50, 50)
  117.  
  118. /*
  119. * 绘制一个填充矩形,这个方法不会产生任何路径:
  120. * ctx.fillRect( 起点x轴坐标,起点y轴坐标,宽,高 )
  121. * */
  122. ctx.fillRect(30, 170, 50, 50)
  123.  
  124. }
  125.  
  126. function d (ctx, cvs) {
  127. /*
  128. * 按照矩形的大小来清除画布中指定位置的内容:
  129. * ctx.clearRect( 起点x轴坐标,起点y轴坐标,宽,高 );
  130. * */
  131. ctx.clearRect(0, 0, cvs.width, cvs.height)
  132.  
  133. }
  134.  
  135. /* 渐变矩形 画一堆横线,加上rgb 线条*/
  136. function lineGarden (ctx) {
  137. // 需求,在50,50点绘制一个宽高各100的渐变矩形
  138. var i = 0, len = 100
  139. for (; i < len; i++) {
  140. // 为了防止重绘
  141. ctx.beginPath()
  142. ctx.moveTo(50, 50 + i)
  143. ctx.lineTo(150, 50 + i)
  144. // 红色通道值依次累加
  145. ctx.strokeStyle = 'rgb(' + 0 + ', ' + Math.floor(255 / 99 * i) + ', ' + 255 + ' )'
  146. // ctx.strokeStyle = 'rgb(' + 0 + ', ' + i + ', ' + 255 + ' )';
  147. ctx.stroke()
  148. }
  149. }
  150. </script>
  151. </body>
  152. </html>

3. canvas 折线图

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <style>
  7. canvas {
  8. border: 1px solid red;
  9. }
  10. </style>
  11. </head>
  12. <body>
  13. 0.各部分都可单独研究绘画细节
  14. 1.定义坐标轴距离画布上下左右的边距
  15. 定义线条粗细
  16. 2.求横坐标原点,x轴顶点,y轴顶点坐标,并画x/y轴
  17. 3.定义箭头的宽高,把箭头当成一个矩形,放大可看细节,并填充
  18. 4.画任意点,把点当成矩形来画 fillRect() 宽高为2,为1的话颜色太浅, 宽高可以适当变大变小
  19. 5.画折线,连接的点实际上连接的是小矩形的左上角顶点,要偏移一下坐标,坐标偏移小矩形宽高的一半,使线穿过小矩形的中心
  20. 6.计算 x/y轴的长度,计算数据的缩放比例
  21. 7.[1,5640,654,2,2,6,5,3,56] 根据y轴的缩放比例来修改原数据,根据x轴的缩放比例来显示各个点的间距
  22.  
  23. <canvas id="cvs" width="500" height="500"></canvas>
  24. <script>
  25. var cvs = document.getElementById('cvs');
  26. var ctx = cvs.getContext('2d');
  27.  
  28. ctx.lineWidth = 2;
  29.  
  30. // 坐标轴距离画布上右下左的边距
  31. var padding = {
  32. top: 20,
  33. right: 20,
  34. bottom: 20,
  35. left: 20
  36. }
  37.  
  38. // 坐标轴中箭头的宽和高
  39. var arrow = {
  40. width: 12,
  41. height: 20
  42. }
  43.  
  44. // 求坐标轴上顶点的坐标
  45. var vertexTop = {
  46. x: padding.left,
  47. y: padding.top
  48. }
  49.  
  50. // 求坐标轴原点的坐标
  51. var origin = {
  52. x: padding.left,
  53. y: cvs.height - padding.bottom
  54. }
  55.  
  56. // 求坐标轴右顶点的坐标
  57. var vertexRight = {
  58. x: cvs.width - padding.right,
  59. y: cvs.height - padding.bottom
  60. }
  61.  
  62. // 画坐标轴中的两条线
  63. ctx.moveTo( vertexTop.x, vertexTop.y );
  64. ctx.lineTo( origin.x, origin.y );
  65. ctx.lineTo( vertexRight.x, vertexRight.y );
  66. ctx.stroke();
  67.  
  68. // 画上顶点箭头
  69. ctx.beginPath();
  70. ctx.moveTo( vertexTop.x, vertexTop.y );
  71. ctx.lineTo( vertexTop.x - arrow.width / 2, vertexTop.y + arrow.height );
  72. ctx.lineTo( vertexTop.x, vertexTop.y + arrow.height / 2 );
  73. ctx.lineTo( vertexTop.x + arrow.width / 2, vertexTop.y + arrow.height );
  74. ctx.closePath();
  75. ctx.fill();
  76.  
  77. // 画右顶点箭头
  78. ctx.beginPath();
  79. ctx.moveTo( vertexRight.x, vertexRight.y );
  80. ctx.lineTo( vertexRight.x - arrow.height, vertexRight.y - arrow.width / 2 );
  81. ctx.lineTo( vertexRight.x - arrow.height / 2, vertexRight.y );
  82. ctx.lineTo( vertexRight.x - arrow.height, vertexRight.y + arrow.width / 2 );
  83. ctx.closePath();
  84. ctx.fill();
  85.  
  86. // 求坐标轴默认可显示数据的最大值
  87. coordMaxX = cvs.width - padding.left - padding.right - arrow.height;
  88. coordMaxY = cvs.height - padding.top - padding.bottom - arrow.height;
  89.  
  90. /*
  91. * 在坐标轴中指定位置画点,坐标算法:
  92. * 点的x轴:原点x坐标 + 点到原点的水平距离
  93. * 点的y轴:原点y坐标 - 点到原点的垂直距离
  94. * */
  95.  
  96. // 需求,利用折线图的方式展示一下门口大爷酱香饼每日销售量
  97. // [ 10, 20, 50, 80, 120, 300, 100, 50, 2 ];
  98.  
  99. var data = [ 100, 200, 400, 600, 1200, 1800, 1000, 500, 20 ];
  100.  
  101. // 求数据缩放的比例
  102. var ratioX = coordMaxX / data.length;
  103. var ratioY = coordMaxY / Math.max.apply( null, data );
  104.  
  105. // 根据比例,对元数据进行缩放
  106. var ratioData = data.map( function( val, i ) {
  107. return val * ratioY;
  108. });
  109.  
  110. // 画点
  111. ratioData.forEach( function( val, index ) {
  112. ctx.fillRect( origin.x + ( index * ratioX) - 2, origin.y - val - 2, 4, 4 );
  113. });
  114.  
  115. // 画折线
  116. ctx.beginPath();
  117. ratioData.forEach( function( val, index ) {
  118. ctx.lineTo( origin.x + ( index * ratioX), origin.y - val );
  119. });
  120. ctx.stroke();
  121. </script>
  122. </body>
  123. </html>

4. canvas 饼图

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <style>
  7. canvas {
  8. border: 1px solid red;
  9. }
  10. p{
  11. line-height: 30px;
  12. margin:0;
  13. }
  14. </style>
  15. </head>
  16. <body>
  17. <p>混入式继承,换种方式的原型继续 Person.prototype={}</p>
  18. 画扇形 <br/>
  19. <p>1.计算数据占的比例 i/sum*360度</p>
  20. <p>2. 度数转为弧度</p>
  21. <p>3.每一个扇形的开始弧度等于上一个扇形的结束弧度
  22. 每一个扇形的结束弧度等于上一个扇形的结束弧度+所占的弧度</p>
  23. <p>4. 画扇形 填充</p>
  24. <p>5.0计算扇形平分线的坐标(即圆上点的坐标)</p>
  25. <p>5.1画平分线,并延长(延长半径,则平分钱也延长了)并填充颜色,覆盖点扇形内的线</p>
  26. <p>6绘制文字</p>
  27. <canvas id="cvs" width="500" height="500"></canvas>
  28. <script>
  29. (function (w) {
  30.  
  31. // 把角度转换为弧度
  32. function angleToRadian (angle) {
  33. return Math.PI / 180 * angle
  34. }
  35.  
  36. // 混入式继承
  37. function extend (o1, o2) {
  38. for (var key in o2) {
  39. // 只有o2自己的属性才会copy到o1身上
  40. if (o2.hasOwnProperty(key)) {
  41. o1[key] = o2[key]
  42. }
  43. }
  44. }
  45.  
  46. /*
  47. * constrcutor { Pipe } 饼图构造函数
  48. * param { x: number } 圆心x轴坐标
  49. * param { y: number } 圆心y轴坐标
  50. * param { r: number } 圆半径
  51. * param { data: Array } 绘制饼图所需的数据
  52. * */
  53. function Pipe (x, y, r, data) {
  54.  
  55. this.x = x
  56. this.y = y
  57. this.r = r
  58. this.data = data
  59.  
  60. // 一组颜色
  61. this.colors = ['orange', 'orchid', 'palegoldenrod', 'palegreen', 'paleturquoise', 'peru', 'pink']
  62. }
  63.  
  64. // 给原型扩充方法
  65. extend(Pipe.prototype, {
  66.  
  67. // 绘制饼图
  68. draw: function () {
  69.  
  70. // 在外面保存一下this
  71. var self = this
  72.  
  73. // 数据的总和
  74. var num = 0
  75. this.data.forEach(function (obj) {
  76. num += obj.val
  77. })
  78.  
  79. // 一个数据值所占用的角度
  80. var baseAngle = 360 / num
  81.  
  82. // 假设一开始就绘制了一个起始为0,结束为0的扇形
  83. var startAngle = 0,
  84. endAngle = 0,
  85. lineAngle = 0,
  86. lineX, lineY
  87.  
  88. // 画扇形
  89. this.data.forEach(function (obj, i) {
  90.  
  91. // 每次进来,计算当前扇形的起始角度和结束角度
  92.  
  93. // 下一个扇形的起始角度,是当前扇形的结束角度
  94. startAngle = endAngle
  95. // 这个结束角度 = 上一个扇形的结束角度 + 当前数值所对应的角度
  96. endAngle = endAngle + baseAngle * obj.val
  97.  
  98. // 求扇形中间线的角度
  99. lineAngle = startAngle + baseAngle * obj.val / 2;
  100. /*
  101. * 根据中间线的角度,求中间的线的x和y坐标:
  102. * x = 圆心x + r * Math.cos( angleToRadian( pointAngle ) )
  103. * y = 圆心y + r * Math.sin( angleToRadian( pointAngle ) )
  104. * */
  105. lineX = self.x + ( self.r + 20 ) * Math.cos( angleToRadian( lineAngle ) );
  106. lineY = self.y + ( self.r + 20 ) * Math.sin( angleToRadian( lineAngle ) );
  107.  
  108. // 第一个扇形
  109. ctx.beginPath()
  110. ctx.moveTo(self.x, self.y)
  111. ctx.arc(self.x, self.y, self.r, angleToRadian(startAngle), angleToRadian(endAngle))
  112. ctx.closePath()
  113. ctx.fillStyle = self.colors[i]
  114. ctx.fill()
  115.  
  116. // 画每一个扇形的平分线
  117. ctx.beginPath();
  118. ctx.moveTo( self.x, self.y );
  119. ctx.lineTo( lineX, lineY );
  120. ctx.strokeStyle = self.colors[ i ];
  121. ctx.stroke();
  122.  
  123. // 绘制文字
  124. if ( lineAngle >= 90 && lineAngle <= 270 ) {
  125. ctx.textAlign = 'right';
  126. }else {
  127. ctx.textAlign = 'left';
  128. }
  129. ctx.fillText( obj.msg, lineX, lineY );
  130. })
  131. }
  132. })
  133.  
  134. // 把构造函数暴露到全局
  135. w.Pipe = Pipe
  136.  
  137. }(window));
  138.  
  139. var cvs = document.getElementById('cvs')
  140. var ctx = cvs.getContext('2d')
  141.  
  142. // var pipe = new Pipe( 200, 200, 80, [ 10, 30, 50, 60, 20 ] );
  143. // [ 10, 30, 50, 60, 20 ]
  144. var pipe = new Pipe(200, 200, 80, [
  145. {
  146. val: 10,
  147. msg: '米饭'
  148. },
  149. {
  150. val: 30,
  151. msg: '面条'
  152. },
  153. {
  154. val: 50,
  155. msg: '馒头'
  156. },
  157. {
  158. val: 50,
  159. msg: '豆腐脑'
  160. },
  161. {
  162. val: 50,
  163. msg: '饺子'
  164. },
  165. {
  166. val: 90,
  167. msg: '汤圆'
  168. },
  169. ])
  170. pipe.draw()
  171.  
  172. </script>
  173. </body>
  174. </html>

5.canvas 生成图片、画弧、扇形、文字

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>canvas</title>
  6. </head>
  7. <style>
  8. canvas {
  9. border: 1px solid red;
  10. }
  11.  
  12. p {
  13. border: 2px solid blue;
  14. padding: 10px;
  15. margin-right: 10px;
  16. }
  17. </style>
  18. <body>
  19. <canvas id="can" width="300" height="300"></canvas>
  20. <div style="display: flex;">
  21. <p class="juxing">虚线 setLineDash 生成图片 canvas.toDataUrl('image/png')</p>
  22. <p class="triangle">画弧</p>
  23. <p class="triangle2">扇形</p>
  24. <p class="middleEmpty">清空画布</p>
  25. <p class="bian">文字</p>
  26. </div>
  27. <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
  28. <script>
  29. let cvs = document.getElementById('can')
  30. let ctx = cvs.getContext('2d')
  31. $('.juxing').click(function () {
  32. a(ctx, cvs)
  33. })
  34. $('.triangle').click(function () {
  35. b(ctx)
  36. })
  37. $('.triangle2').click(function () {
  38. c(ctx)
  39. })
  40. $('.middleEmpty').click(function () {
  41. d(ctx, cvs)
  42. })
  43. $('.bian').click(function () {
  44. e(ctx)
  45. })
  46.  
  47. /*
  48. * 设置画线的时候空白部分和实线部分的大小。
  49. * ctx.setLineDash( [ 5, 3 ] )
  50. * 参数可以任意多个
  51. * */
  52.  
  53. function a (ctx, cvs) {
  54. ctx.beginPath()
  55.  
  56. ctx.lineDashOffset = 3 // 设置偏移量,进行微调用,效果不明显
  57. ctx.setLineDash([5, 3]) // 5像素实线,3像素空白,则变成了虚线
  58. ctx.moveTo(10, 10)
  59. ctx.lineTo(210, 10)
  60. ctx.stroke()
  61.  
  62. let url = cvs.toDataURL('image/png')
  63. let img = document.createElement('img')
  64. img.src = url
  65. document.body.appendChild(img)
  66. /*
  67. * 获取线条绘制规则。
  68. * ctx.getLineDash()
  69. * */
  70. console.log(ctx.getLineDash())
  71. }
  72.  
  73. /*
  74. * 画弧( 画的是路径 )
  75. * ctx.arc( 圆心x轴坐标,圆心y轴坐标,半径, 起点弧度,结束点弧度,是否逆时针画(可选) )
  76. * arc方法内部会先从路径结束点到弧的起点画一条路径线。
  77. * 起点弧度、结束点弧度以及弧度的方向共同决定了弧的大小。
  78. * */
  79. // 把角度转换为弧度
  80. function angleToRadian (angle) {
  81. return Math.PI / 180 * angle
  82. }
  83.  
  84. function b (ctx) {
  85. ctx.beginPath()
  86. // 顺时针画一段弧 从x轴水平线右侧开始 默认顺时针
  87. ctx.arc(100, 100, 30, angleToRadian(90), angleToRadian(270))
  88. ctx.stroke()
  89. // 逆时针画一段弧
  90. ctx.beginPath()
  91. ctx.arc(200, 100, 30, angleToRadian(90), angleToRadian(270), true)
  92. ctx.stroke()
  93. }
  94.  
  95. function c (ctx) {
  96. ctx.beginPath()
  97. /*
  98. * 画扇形:
  99. * 1、先设置路径起点为圆心
  100. * 2、画弧
  101. * 3、闭合路径
  102. * */
  103. ctx.beginPath()
  104. ctx.moveTo(100, 100) // arc方法内部会先从路径结束点到弧的起点画一条路径线。
  105. ctx.arc(100, 100, 90, angleToRadian(220), angleToRadian(310))
  106. ctx.closePath()
  107. ctx.stroke()
  108. }
  109.  
  110. function d (ctx, cvs) {
  111. ctx.clearRect(0, 0, cvs.width, cvs.height)
  112. ctx.setLineDash([]) // 清空虚线
  113. }
  114.  
  115. /*
  116. * 设置文字的属性
  117. * ctx.font = 和css语法一样。
  118. * 注意:这里设置字体大小时必须带单位,单位支持css的所有表示方式。
  119. * 注意:单独设置字体大小不会生效,必须要加一个额外属性样式。
  120.  
  121. ctx.strokeText( 描边文字, 参考x轴坐标,参考y轴坐标,限制文字的最大长度(可选) )
  122. ctx.fillText( 填充文字, 参考x轴坐标,参考y轴坐标,限制文字的最大长度(可选) )
  123.  
  124. * 设置文字的水平对其方式:
  125. * ctx.textAlign = 'left || start' 、 'right || end' 、 'center'
  126. * 默认值为start。
  127.  
  128. * 设置文字的垂直对其方式:
  129. * ctx.textBaseline = 'top' 、'bottom'、'middle'、'alphabetic'、'hanging'、'ideographic'
  130. * 默认值为alphabetic。
  131. * */
  132. function e (ctx) {
  133. ctx.beginPath()
  134. // ctx.font = '3rem 微软雅黑'
  135. ctx.font = '28px 微软雅黑'
  136. ctx.fillStyle = 'deeppink';
  137.  
  138. ctx.textAlign = 'left' // 水平对齐
  139. ctx.textBaseline = 'middle' // 垂直对齐
  140. ctx.strokeText('描边字', 100, 100) // 描边文字,空心字
  141. // ctx.strokeText('中文字',100,100,100) // 第一个参数限制文字宽度,小了则压缩字体
  142. ctx.fillText('中文字', 200, 200) // 填充文字,一般字
  143.  
  144. // 绘制文字的参考点
  145. ctx.beginPath()
  146. ctx.arc(100, 100, 4, 0, Math.PI * 2)
  147. ctx.fill()
  148.  
  149. // 在画布的左上角绘制一段文字
  150. ctx.textAlign = 'left';
  151. ctx.textBaseline = 'top';
  152. ctx.fillText( '左上角', 0, 0 );
  153.  
  154. // 在画布的右上角绘制一段文字
  155. ctx.textAlign = 'right';
  156. ctx.textBaseline = 'top';
  157. ctx.fillText( '右上角', cvs.width, 0 );
  158.  
  159. }
  160. </script>
  161. </body>
  162. </html>

6. canvas drawImage() 三参数、五参数、九参数、

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>canvas</title>
  6. </head>
  7. <style>
  8. canvas {
  9. border: 1px solid red;
  10. }
  11. </style>
  12. <body>
  13. <img src="NPC5.png" alt="" id="img"> <!-- 160*260 -->
  14. <canvas id="can" width="300" height="360"></canvas>
  15. <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
  16. <script>
  17. let cvs = document.getElementById('can')
  18. let ctx = cvs.getContext('2d')
  19. // 直接画,避开函数调用产生的异步问题
  20. /*
  21. * ctx.drawImage()
  22. * 绘制图像,有三种使用方式。
  23. * 三参数 图像、坐标x,坐标y
  24. * 五参数 图像、坐标x,坐标y, 图片宽,图片高
  25. * 九参数 把裁剪到的部分图像绘制到指定的坐标,并指定其大小。
  26. * drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh)
  27. * sx, sy, sw, sh 切原图一小块的坐标宽高
  28. * dx,dy,dw,dh 是最终图片的坐标,宽高
  29. * */
  30.  
  31. let img = document.getElementById('img')
  32. img.onload = function () {
  33. // ctx.drawImage(img, 10, 10)
  34. // ctx.drawImage(img, 10, 100, img.width, img.height)
  35.  
  36. // drawImage(image, dx, dy)
  37. // drawImage(image, dx, dy, dw, dh)
  38. // drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh)
  39.  
  40. ctx.drawImage(img, 0, img.height / 4 * 2, img.width / 4, img.height / 4,
  41. 40, 140, img.width / 4, img.height / 4)
  42.  
  43. let i = 0, step = 0
  44. let interval = setInterval(() => {
  45. ctx.clearRect(80, 140, cvs.width, cvs.height)
  46. ctx.drawImage(img, img.width / 4 * i, img.height / 4, img.width / 4, img.height / 4,
  47. 180 - step * 5, 140, img.width / 4, img.height / 4)
  48. i++
  49. step++
  50. if (i > 3) {
  51. i = 0
  52. }
  53. if (180 - step * 5 < 80) {
  54. window.clearInterval(interval)
  55. }
  56. }, 100)
  57. }
  58. </script>
  59. </body>
  60. </html>

7.canvas 平移 translate、旋转 rotate、缩放 scale

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <style>
  7. canvas {
  8. border: 1px solid red;
  9. }
  10. </style>
  11. </head>
  12.  
  13. <body>
  14. <canvas width="300" height="300" id="can"></canvas>
  15. <script>
  16. let cvs = document.getElementById('can')
  17. let ctx = cvs.getContext('2d')
  18.  
  19. /*
  20. * 平移,移动原来的矩形
  21. * 平移、缩放、旋转会叠加
  22. * */
  23. ctx.fillRect(30, 30, 20, 20)
  24. ctx.translate(20, 20)
  25. ctx.fillStyle = 'blue'
  26. ctx.fillRect(30, 30, 20, 20)
  27.  
  28. /*
  29. * 旋转 相对于原点的旋转
  30. * 先平移到中间某位置
  31. * */
  32. ctx.translate(100, 100)
  33. ctx.fillRect(0, 0, 30, 30) // 从 (0,0)开始
  34.  
  35. ctx.rotate(Math.PI / 6)
  36. ctx.fillStyle = 'red'
  37. ctx.fillRect(0, 0, 30, 30)
  38.  
  39. ctx.rotate(Math.PI / 6)
  40. ctx.fillStyle = 'pink'
  41. ctx.fillRect(0, 0, 30, 30)
  42.  
  43. /*
  44. * 缩放 相对于原点的缩放
  45. * 先平移到中间某位置
  46. * 最好单独试,免得叠加计算出错
  47. *
  48. * */
  49. ctx.rotate(-Math.PI / 6*2) // 旋转回来
  50. ctx.translate(60, 60)
  51. ctx.fillRect(0, 0, 40, 40)
  52. ctx.scale(0.5, 0.5)
  53. ctx.fillStyle = 'blue'
  54. ctx.fillRect(0, 0, 40, 40)
  55.  
  56. </script>
  57. </body>
  58. </html>

8.工厂模式 函数返回时   return new Person(name,age)

  1. /* 工厂模式 */
  2. function Person (name, age) {
  3. this.name = name
  4. this.age = age
  5. }
  6.  
  7. // 工厂
  8. // 工厂模式相当于省去new关键字
  9. function getPerson (name, age) {
  10. return new Person(name, age)
  11. }
  12.  
  13. console.log(getPerson('女神', 18))

9.状态保存、回滚 ctx.save()   ctx.restore()   判断点在画布中, 旋转图形绘制(第9不太懂)

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>canvas</title>
  6. </head>
  7. <style>
  8. canvas {
  9. border: 1px solid red;
  10. }
  11.  
  12. p {
  13. border: 2px solid blue;
  14. padding: 10px;
  15. margin-right: 10px;
  16. }
  17. </style>
  18. <body>
  19. <canvas id="can" width="300" height="360"></canvas>
  20. <div style="display: flex;">
  21. <p class="juxing">状态保存、回滚 ctx.save() restore()</p>
  22. <p class="triangle">判断点在画布中</p>
  23. </div>
  24. <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
  25. <script>
  26. let cvs = document.getElementById('can')
  27. let ctx = cvs.getContext('2d')
  28.  
  29. /*
  30. * 绘制一个旋转图形的步骤:
  31. * 1、先平移坐标轴到图形的中心
  32. * 2、旋转坐标轴
  33. * 3、绘制图形( 需要注意,平移旋转之后,坐标体系变化,不能按照之前定好的坐标来绘制旋转图形 )
  34. * */
  35.  
  36. /* // 正常情况下的参考矩形
  37. ctx.fillStyle = 'pink';
  38. ctx.fillRect( 100, 100, 50, 50 ); // 原来的图形
  39.  
  40. // 平移到矩形的中心
  41. ctx.translate( 125, 125 );
  42. // 旋转坐标系
  43. ctx.rotate( Math.PI / 180 * 30 );
  44. // 绘制图形
  45. ctx.fillStyle = 'blue';
  46. ctx.fillRect( -25, -25, 50, 50 ); // 新坐标为宽高的一半,不懂。*/
  47.  
  48. // 定时器
  49. // 先统一平移到矩形的中心
  50. ctx.translate(125, 125)
  51. // 基于这个中心不断绘制旋转矩形
  52. setInterval(function () {
  53. // 清除上一次的矩形
  54. ctx.clearRect(-50, -50, cvs.width, cvs.height)
  55. // 旋转坐标系
  56. ctx.rotate(Math.PI / 180 * 4)
  57. // 绘制图形
  58. ctx.fillRect(-25, -25, 50, 50)
  59. }, 50)
  60.  
  61. /* 工厂模式 */
  62. function Person (name, age) {
  63. this.name = name
  64. this.age = age
  65. }
  66.  
  67. // 工厂
  68. // 工厂模式相当于省去new关键字
  69. function getPerson (name, age) {
  70. return new Person(name, age)
  71. }
  72.  
  73. console.log(getPerson('女神', 18))
  74.  
  75. /**
  76. * 状态保存: ctx.save();
  77. * 状态回滚: ctx.restore();
  78. * */
  79. $('.juxing').click(function () {
  80. // 保存下面的状态
  81. ctx.save()
  82. ctx.lineWidth = 10
  83. ctx.strokeStyle = 'blue'
  84.  
  85. ctx.moveTo(10, 10)
  86. ctx.lineTo(210, 10)
  87. ctx.stroke()
  88.  
  89. // 再保存下面的状态
  90. ctx.save()
  91. ctx.strokeStyle = 'green'
  92.  
  93. ctx.beginPath()
  94. ctx.moveTo(10, 60)
  95. ctx.lineTo(210, 60)
  96. ctx.stroke()
  97.  
  98. // 回滚
  99. ctx.restore()
  100. ctx.beginPath()
  101. ctx.moveTo(10, 90)
  102. ctx.lineTo(210, 90)
  103. ctx.stroke()
  104.  
  105. })
  106.  
  107. $('.triangle').click(function () {
  108. /*
  109. * 判断点在不在路径中:
  110. * ctx.isPointInPath( 要判断的点x轴坐标,要判断的点y轴坐标 )
  111. * */
  112.  
  113. ctx.rect(10, 10, 50, 50)
  114. ctx.stroke()
  115.  
  116. // 点击画布,判断点击的位置在不在路径中
  117. cvs.addEventListener('click', function (e) {
  118. var x = e.pageX - cvs.offsetLeft
  119. var y = e.pageY - cvs.offsetTop
  120. alert(ctx.isPointInPath(x, y))
  121. })
  122.  
  123. })
  124.  
  125. </script>
  126. </body>
  127. </html>

10 监听者模式(不懂)

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. <script>
  9.  
  10. // 一个监听者 服务与 多个听众
  11. // 监听者
  12. var jianTingZhe = {
  13.  
  14. // 听众列表
  15. listeners: {
  16. birdOver: [],
  17. birdFlappy: [],
  18. birdRotate: []
  19. },
  20.  
  21. // 小鸟死亡触发时,告知所有监听死亡的听众
  22. triggerBirdOver: function() {
  23. this.listeners.birdOver.forEach( function( listen ) {
  24. listen();
  25. });
  26. },
  27.  
  28. // 小鸟飞翔的时候,告知所有监听飞翔的听众
  29. triggerBirdFlappy: function() {
  30. this.listeners.birdFlappy.forEach( function( listen ) {
  31. listen();
  32. });
  33. },
  34.  
  35. // 小鸟飞翔的时候,告知所有监听飞翔的听众
  36. triggerBirdRotate: function() {
  37. this.listeners.birdRotate.forEach( function( listen ) {
  38. listen();
  39. });
  40. }
  41.  
  42. };
  43.  
  44. // 这是一个模块,整体可以认为是一个听众监听N多事件
  45. (function( w ) {
  46. // 小鸟死亡听众
  47. jianTingZhe.listeners.birdOver.push( function() {
  48. console.log( '小鸟死了,我就哭' );
  49. } );
  50. jianTingZhe.listeners.birdOver.push( function() {
  51. console.log( '小鸟死了,我很伤心' );
  52. } );
  53. jianTingZhe.listeners.birdOver.push( function() {
  54. console.log( '小鸟死了,我要埋葬它' );
  55. } );
  56.  
  57. // 小鸟飞翔听众
  58. jianTingZhe.listeners.birdFlappy.push( function() {
  59. console.log( '小鸟飞了,我很搞笑' );
  60. });
  61. jianTingZhe.listeners.birdFlappy.push( function() {
  62. console.log( '小鸟飞了,我要把射下来' );
  63. });
  64.  
  65. // 小鸟旋转听众
  66. jianTingZhe.listeners.birdRotate.push( function() {
  67. console.log( '小鸟转了,呱唧呱唧!' );
  68. });
  69. }( window ));
  70.  
  71. // 这是另一个模块,整体可以认为是一个听众
  72. (function( w ) {
  73. // 小鸟旋转听众
  74. jianTingZhe.listeners.birdRotate.push( function() {
  75. console.log( '我是模块2' );
  76. });
  77. }( window ));
  78.  
  79. // 监听到小鸟死了
  80. jianTingZhe.triggerBirdOver();
  81. // 监听到小鸟转了
  82. jianTingZhe.triggerBirdRotate()
  83. // 监听到小鸟飞翔了
  84. jianTingZhe.triggerBirdFlappy()
  85. </script>
  86. </body>
  87. </html>

11.动画帧函数  requestAnimationFrame 函数回调的触发是由浏览器来控制的,行就会比较稳定,适合用来做流畅的动画。

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <style>
  7. div {
  8. height: 20px;
  9. background-color: black;
  10. }
  11. </style>
  12. </head>
  13. <body>
  14. <div id="div"></div>
  15. <script>
  16. /*
  17. * 请求动画帧函数,这个函数和setTimeout方法使用类似,
  18. * 他都是定时器,却别在于setTimeout可以自由指定回调的触发时间,
  19. * 而requestAnimationFrame函数回调的触发是由浏览器来控制的。
  20. *
  21. * requestAnimationFrame( callback )
  22. * 备注:当浏览器重绘页面的时候,就会调用这个callback,
  23. * 这样callbackg的执行就会比较稳定,适合用来做流畅的动画。
  24. * */
  25.  
  26. /*setInterval( function() {
  27. console.log(111);
  28. }, 50);*/
  29.  
  30. /*function con() {
  31. console.log(111);
  32. setTimeout( con, 50);
  33. }
  34. setTimeout( con, 50);*/
  35.  
  36. // 简化setTimeout不断执行回调的方式
  37. /*(function con() {
  38. console.log(111);
  39. setTimeout( con, 50);
  40. }());*/
  41.  
  42. // 把setTimeout改为requestAnimationFrame
  43. (function con() {
  44. console.log(111);
  45. requestAnimationFrame( con );
  46. }());
  47. </script>
  48. </body>
  49. </html>

12. ctx2.drawImage( cvs1, 0, 0 );  // 把第一个canvas的内容绘制到第二个canvas中

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <style>
  7. div {
  8. height: 20px;
  9. background-color: black;
  10. }
  11. </style>
  12. </head>
  13. <body>
  14. <canvas id="cvs1"></canvas>
  15. <canvas id="cvs2"></canvas>
  16. <script>
  17. /*
  18. * drawImage的第一个参数可以是img、canvas或video
  19. * */
  20.  
  21. var cvs1 = document.querySelector( '#cvs1' );
  22. var cvs2 = document.querySelector( '#cvs2' );
  23.  
  24. var ctx1 = cvs1.getContext( '2d' );
  25. var ctx2 = cvs2.getContext( '2d' );
  26.  
  27. // 给第一个画布绘制内容
  28. ctx1.fillRect( 10, 10, 100, 100 );
  29.  
  30. // 把第一个canvas的内容绘制到第二个canvas中
  31. ctx2.drawImage( cvs1, 0, 0 );
  32. ctx2.fillStyle = 'blue';
  33. ctx2.fillRect( 0, 0, 50, 50 );
  34.  
  35. </script>
  36. </body>
  37. </html>

 

canvas20181114的更多相关文章

随机推荐

  1. bash中打印文件每一行及其行号

    #!/bin/bash linenumber=$(cat remoteIP.cfg |wc -l) currentline= for ip in $(cat remoteIP.cfg) do curr ...

  2. spring 中的设计模式

    https://mp.weixin.qq.com/s?__biz=MzU0MDEwMjgwNA==&mid=2247485205&idx=1&sn=63455d2313776d ...

  3. Android studio Error: Modules no specified解决和真机调试

    如何配置SDK百度一大堆: 前言:Android Studio很完善,如果SDK配置好,理论上就是 创建项目->创建个APP(名字自己随便起)->打开手机开发者模式运行即可:如果出了问题, ...

  4. HTTP协议6之状态码--转

    HTTP状态码,我都是现查现用. 我以前记得几个常用的状态码,比如200,302,304,404, 503. 一般来说我也只需要了解这些常用的状态码就可以了.  如果是做AJAX,REST,网络爬虫, ...

  5. 二叉树(BT)相关

    1.same tree /** * Definition for binary tree * public class TreeNode { * int val; * TreeNode left; * ...

  6. SQL判断语句

    ,,decode(tts.execute_state,,'false','true')) from twf_tech_schedule tts sql判断语句

  7. 20155324《网络对抗》Exp1 PC平台逆向破解(5)M

    20155324<网络对抗>Exp1 PC平台逆向破解(5)M 实验目标 本次实践的对象是一个名为~pwn1~的~linux~可执行文件. 该程序正常执行流程是:~main~调用~foo~ ...

  8. 【2】学习C++之引用

    C++中的引用类似于现实生活中人们之间起昵称,昵称和本名都可以辨别人. 1.普通变量的引用: ;//a为本名 int &b=a;//b为a的昵称 其中不能光有昵称没有本名,如果只定义了引用,却 ...

  9. 20175306 迭代和JDB调试

    迭代和JDB调试 1.使用C(n,m)=C(n-1,m-1)+C(n-1,m)公式进行递归编程实现求组合数C(m,n)的功能 代码展示: public class C { public static ...

  10. 自己写的一个用js把select换成div与span与ul的东西

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...