七巧板本质上就是 分别由几个直线 拼成一个个图形,再将这些图形结合起来
- var tangram = [
- { p: [{ x: 0, y: 0 }, { x: 800, y: 0 }, { x: 400, y: 400 }], color: "#caff67" },
- { p: [{ x: 0, y: 0 }, { x: 400, y: 400 }, { x: 0, y: 800 }], color: "#67beef" },
- { p: [{ x: 800, y: 0 }, { x: 800, y: 400 }, { x: 600, y: 600 }, { x: 600, y: 200 }], color: "#ef3d61" },
- { p: [{ x: 600, y: 200 }, { x: 600, y: 600 }, { x: 400, y: 400 }], color: "#f9f5la" },
- { p: [{ x: 400, y: 400 }, { x: 600, y: 600 }, { x: 400, y: 800 }, { x: 200, y: 600 }], color: "#a594c0" },
- { p: [{ x: 200, y: 600 }, { x: 400, y: 800 }, { x: 0, y: 800 }], color: "#fa8ecc" },
- { p: [{ x: 800, y: 400 }, { x: 800, y: 800 }, { x: 400, y: 800 }], color: "#f6ca29" }
- ]
- const canvas = document.getElementById('canvas')
- canvas.width = 800
- canvas.height = 800
- const context = canvas.getContext('2d')
-
- for (let i = 0; i < tangram.length; i++) {
- draw(tangram[i], context)
- }
-
- function draw(piece, cxt) {
- cxt.beginPath()
- cxt.moveTo(piece.p[0].x, piece.p[0].y)
- for (var i = 1; i < piece.p.length; i++) {
- cxt.lineTo(piece.p[i].x, piece.p[i].y)
- }
- cxt.closePath()
-
- cxt.fillStyle = piece.color
- cxt.fill()
-
- cxt.strokeStyle = "black"
- cxt.lineWidth = 3
- cxt.stroke()
- }
图示:

- context.beginPath()
- context.moveTo(100, 350)
- context.lineTo(500, 350)
- context.lineTo(500, 200)
- context.lineTo(700, 400)
- context.lineTo(500, 600)
- context.lineTo(500, 450)
- context.lineTo(100, 450)
- context.closePath()
-
- context.lineWidth = 5
- context.strokeStyle = '#058'
-
- context.stroke()
图示:

如下图所示:五角星外面的五个顶点都在外圆上,里面的五个顶点都在内圆上
五角星的10个顶点,外圆的每个顶点相差72度,同理,内圆的每个顶点也相差72度
算出每个顶点的坐标
最后用线段连接起来

代码:
- const canvas = document.getElementById('canvas')
- canvas.width = 800
- canvas.height = 800
- const context = canvas.getContext('2d')
-
- const translateX = 400 // 让圆心在X轴的中心位置
- const bigRadius = 300 // 大圆半径
- const smallRadius = 150 // 小圆半径
- context.beginPath()
- for(let i = 0; i < 5; i++) {
- context.lineTo(
- Math.cos((18 + i * 72) / 180 * Math.PI) * bigRadius + translateX,
- -Math.sin((18 + i * 72) / 180 * Math.PI) * bigRadius + translateX
- )
- context.lineTo(
- Math.cos((54 + i * 72) / 180 * Math.PI) * smallRadius + translateX,
- -Math.sin((54 + i * 72) / 180 * Math.PI) * smallRadius + translateX
- )
- }
- context.closePath()
-
- context.lineWidth = 10
- context.stroke()
图示:


代码:
- <!DOCTYPE html>
- <html lang="en">
-
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Document</title>
- </head>
-
- <body>
- <canvas id="canvas" style="border:1px solid #ccc;display:block;margin:50px auto;"></canvas>
-
- <script>
- const canvas = document.getElementById('canvas')
- canvas.width = 800
- canvas.height = 800
- const context = canvas.getContext('2d')
-
- fillMoon(context, 2, 400, 400, 300, 0)
-
- function fillMoon(cxt, d, x, y, R, rot, fillColor) {
- cxt.save()
- cxt.translate(x, y)
- cxt.rotate(rot * Math.PI / 180)
- cxt.scale(R, R)
- pathMoon(cxt, d)
- cxt.fillStyle = fillColor || '#fb5'
- cxt.fill()
- cxt.restore()
- }
-
- function pathMoon(cxt, d) {
- cxt.beginPath()
- cxt.arc(0, 0, 1, 0.5*Math.PI, 1.5*Math.PI, true)
- cxt.moveTo(0, -1)
- cxt.arcTo(d, 0, 0, 1, dis(0, -1, d, 0) / d)
- cxt.closePath()
- }
-
- function dis(x1, y1, x2, y2) {
- return Math.sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2))
- }
-
- </script>
- </body>
-
- </html>
图示:

- <!DOCTYPE html>
- <html lang="en">
-
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Document</title>
- </head>
-
- <body>
- <canvas id="canvas" style="border:1px solid #ccc;display:block;margin:50px auto;"></canvas>
-
- <script>
- const canvas = document.getElementById('canvas')
- canvas.width = 1200
- canvas.height = 800
- const context = canvas.getContext('2d')
-
- const skyStyle = context.createLinearGradient(0, 0, 0, canvas.height)
- skyStyle.addColorStop(0.0, 'black')
- skyStyle.addColorStop(1.0, '#035')
- context.fillStyle = skyStyle
- context.fillRect(0, 0, canvas.width, canvas.height)
-
- for (let i = 0; i < 200; i++) {
- const R = Math.random() * 5 + 5
- const r = R / 2.0
- const x = Math.random() * canvas.width
- const y = Math.random() * canvas.height * 0.65
- const rot = Math.random() * 360
-
- drawStar(context, r, R, x, y, rot)
- }
-
- fillMoon(context, 2, 900, 200, 100, 30)
-
- drawLand(context)
-
- function drawLand(cxt) {
- cxt.save()
-
- cxt.beginPath()
- cxt.moveTo(0, 600)
- cxt.bezierCurveTo(540, 400, 660, 800, 1200, 600)
- cxt.lineTo(1200, 800)
- cxt.lineTo(0, 800)
- cxt.closePath()
-
- const landStyle = cxt.createLinearGradient(0, 800, 0, 0)
- landStyle.addColorStop(0.0, '#030')
- landStyle.addColorStop(1.0, '#580')
- cxt.fillStyle = landStyle
- cxt.fill()
-
- cxt.restore()
- }
-
- function fillMoon(cxt, d, x, y, R, rot, fillColor) {
- cxt.save()
- cxt.translate(x, y)
- cxt.rotate(rot * Math.PI / 180)
- cxt.scale(R, R)
- pathMoon(cxt, d)
- cxt.fillStyle = fillColor || '#fb5'
- cxt.fill()
- cxt.restore()
- }
-
- function pathMoon(cxt, d) {
- cxt.beginPath()
- cxt.arc(0, 0, 1, 0.5 * Math.PI, 1.5 * Math.PI, true)
- cxt.moveTo(0, -1)
- //cxt.arcTo(d, 0, 0, 1, dis(0, -1, d, 0) / d)
- cxt.quadraticCurveTo(1.2, 0, 0, 1)
- cxt.closePath()
- }
-
- function dis(x1, y1, x2, y2) {
- return Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2))
- }
-
- function drawStar(cxt, r, R, x, y, rot) {
- cxt.save()
-
- cxt.translate(x, y)
- cxt.rotate(rot / 180 * Math.PI)
- cxt.scale(R, R)
-
- starPath(cxt)
-
- cxt.fillStyle = '#fb3'
- // cxt.strokeStyle = '#fd5'
- // cxt.lineWidth = 3
- // cxt.lineJoin = 'round'
-
- cxt.fill()
- //cxt.stroke()
-
- cxt.restore()
- }
-
- function starPath(cxt) {
- cxt.beginPath()
- for (let i = 0; i < 5; i++) {
- cxt.lineTo(
- Math.cos((18 + i * 72) / 180 * Math.PI),
- -Math.sin((18 + i * 72) / 180 * Math.PI)
- )
- cxt.lineTo(
- Math.cos((54 + i * 72) / 180 * Math.PI) * 0.5,
- -Math.sin((54 + i * 72) / 180 * Math.PI) * 0.5
- )
- }
- cxt.closePath()
- }
-
- </script>
- </body>
-
- </html>
图示:

本质上是4条线段和4个弧线,共8个部分组成

代码:
- <!DOCTYPE html>
- <html lang="en">
-
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Document</title>
- </head>
-
- <body>
- <canvas id="canvas" style="border:1px solid #ccc;display:block;margin:50px auto;"></canvas>
-
- <script>
- const canvas = document.getElementById('canvas')
- canvas.width = 800
- canvas.height = 800
- const context = canvas.getContext('2d')
-
- drawRoundRect(context, 100, 100, 600, 400, 20)
-
- function drawRoundRect(cxt, x, y, width, height, radius) {
- cxt.save()
- cxt.translate(x, y)
- pathRoundRect(cxt, width, height, radius)
- cxt.strokeStyle = 'black'
- cxt.stroke()
- cxt.restore()
- }
-
- function pathRoundRect(cxt, width, height, radius) {
- cxt.beginPath()
- cxt.arc(width - radius, height - radius, radius, 0, Math.PI / 2)
- cxt.lineTo(radius, height)
-
- cxt.arc(radius, height - radius, radius, Math.PI / 2, Math.PI)
- cxt.lineTo(0, radius)
-
- cxt.arc(radius, radius, radius, Math.PI, Math.PI * 3 / 2)
- cxt.lineTo(width - radius, 0)
-
- cxt.arc(width - radius, radius, radius, Math.PI * 3 / 2, Math.PI * 2)
- cxt.closePath()
- }
-
- </script>
- </body>
-
- </html>
图示:

- <!DOCTYPE html>
- <html lang="en">
-
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Document</title>
- </head>
-
- <body>
- <canvas id="canvas" style="border:1px solid #ccc;display:block;margin:50px auto;"></canvas>
-
- <script>
- const canvas = document.getElementById('canvas')
- canvas.width = 800
- canvas.height = 800
- const context = canvas.getContext('2d')
-
- fillRoundRect(context, 150, 150, 500, 500, 10, '#bbada0')
- for(let i = 0; i < 4; i++) {
- for (let j = 0; j < 4; j++) {
- fillRoundRect(context, 170+i*120, 170 + j * 120, 100, 100, 6, '#ccc0b3')
- }
- }
-
- function fillRoundRect(cxt, x, y, width, height, radius, fillColor) {
- if (2*radius > width || 2*radius > height) {
- return
- }
-
- cxt.save()
- cxt.translate(x, y)
- pathRoundRect(cxt, width, height, radius)
- cxt.fillStyle = fillColor || 'black'
- cxt.fill()
- cxt.restore()
- }
-
- function strokeRoundRect(cxt, x, y, width, height, radius, lineWidth, strokeColor) {
- if (2 * radius > width || 2 * radius > height) {
- return
- }
-
- cxt.save()
- cxt.translate(x, y)
- pathRoundRect(cxt, width, height, radius)
- cxt.lineWidth = lineWidth || 1
- cxt.strokeStyle = strokeColor || 'black'
- cxt.stroke()
- cxt.restore()
- }
-
- function pathRoundRect(cxt, width, height, radius) {
- cxt.beginPath()
- cxt.arc(width - radius, height - radius, radius, 0, Math.PI / 2)
- cxt.lineTo(radius, height)
-
- cxt.arc(radius, height - radius, radius, Math.PI / 2, Math.PI)
- cxt.lineTo(0, radius)
-
- cxt.arc(radius, radius, radius, Math.PI, Math.PI * 3 / 2)
- cxt.lineTo(width - radius, 0)
-
- cxt.arc(width - radius, radius, radius, Math.PI * 3 / 2, Math.PI * 2)
- cxt.closePath()
- }
-
- </script>
- </body>
-
- </html>
图示:

1