添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
追风的花生  ·  Name resolution and ...·  1 年前    · 
讲道义的茴香  ·  datatables ...·  1 年前    · 
谈吐大方的鸵鸟  ·  spring ...·  1 年前    · 
画一颗圣诞树🎄

画一颗圣诞树🎄

初始化

新建页面,添加一个 canvas 元素,引入 css, js 文件

<!DOCTYPE html>
<html lang="en">
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Christmas Tree</title>
    <link rel="stylesheet" href="style.css" />
  </head>
    <canvas id="tree"></canvas>
    <script src="./index.js"></script>
  </body>
</html>


canvas {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  background: #fefdfd;
  box-shadow: 0 0 2px rgba(0, 0, 0, 0.4);


const CANVAS_WIDTH = 360
const CANVAS_HEIGHT = 620
function initCanvas(id) {
  const canvas = document.getElementById(id)
  canvas.width = CANVAS_WIDTH
  canvas.height = CANVAS_HEIGHT
  return canvas
function main() {
  const canvas = initCanvas('tree')
window.addEventListener('load', main)

画树枝

使用 stroke 方法绘制树枝,设置旋转角度绘制左右子树,保存状态,递归绘制子树。

function main() {
  const canvas = initCanvas('tree')
  // 树的起始位置
  const location = [CANVAS_WIDTH * 0.5, CANVAS_HEIGHT]
  drawBranches(canvas, location, 0, 100, 20)
 * canvas       画布
 * start        起始位置
 * angle        旋转角度
 * branchHeight 树枝长度
 * branchWidth  树枝宽度
function drawBranches(canvas, start, angle, branchHeight, branchWidth) {
  const ctx = canvas.getContext('2d')
  ctx.save()
  ctx.beginPath()
  // 将画布原点移动到起始位置
  ctx.translate(...start)
  // 设置绘制颜色
  ctx.strokeStyle = '#333'
  // 设置绘制宽度
  ctx.lineWidth = branchWidth
  // 设置旋转角度
  ctx.rotate((angle * Math.PI) / 180)
  ctx.moveTo(0, 0)
  ctx.lineTo(0, -branchHeight)
  ctx.stroke()
  if (branchHeight > 6) {
    // 绘制右子树
    drawBranches(canvas, [0, -branchHeight], 35, branchHeight * 0.5, branchWidth * 0.7)
    // 绘制左子树
    drawBranches(canvas, [0, -branchHeight], -35, branchHeight * 0.5, branchWidth * 0.7)
    // 绘制中间的树干
    drawBranches(canvas, [0, -branchHeight], 0, branchHeight * 0.8, branchWidth * 0.7)
  ctx.restore()

画树叶

获取画布所有像素点 alpha 通道值,判断此处是否有图像,循环像素点数组绘制半圆。

function main() {
  const canvas = initCanvas('tree')
  const location = [CANVAS_WIDTH * 0.5, CANVAS_HEIGHT]
  drawBranches(canvas, location, 0, 100, 20)
  drawLeaves(canvas)
// ...
// 使用一个数组保存绘制树的像素点
const branchPixels = []
function drawLeaves(canvas) {
  const ctx = canvas.getContext('2d')
  // 获取画布像素数据
  const imageData = ctx.getImageData(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT)
  const data = imageData.data
  for (let y = 0; y < CANVAS_HEIGHT; y++) {
    for (let x = 0; x < CANVAS_WIDTH; x++) {
      // 获取像素点 alpha 通道值
      const alpha = data[4 * (y * CANVAS_WIDTH + x) + 3]
      // 如果 alpha 值大于 0 说明这个位置有图像;排除基础树干的像素点;
      if (alpha > 0 && y < CANVAS_HEIGHT - 100) {
        branchPixels.push([x, y])
  for (let i = 0; i < branchPixels.length; i++) {
    // 减少绘制几率
    if (Math.random() < 0.3) {
      const loc = branchPixels[i]
      loc[0] += (Math.random() - 0.5) * 5
      loc[1] += (Math.random() - 0.5) * 5
      // 设置绘制颜色,越往外颜色越浅
      const green = (255 * (CANVAS_HEIGHT - loc[1])) / CANVAS_HEIGHT
      ctx.save()
      ctx.beginPath()
      ctx.translate(...loc)
      ctx.rotate(Math.random() * Math.PI * 2)
      ctx.fillStyle = `rgba(0, ${green}, 0, .2)`
      // 绘制半圆
      ctx.arc(0, 0, 5, 0, Math.PI)
      ctx.fill()
      ctx.restore()

画礼物

使用 fillText drawImage 方法绘制文字和图片。

function main() {
  const canvas = initCanvas('tree')
  const location = [CANVAS_WIDTH * 0.5, CANVAS_HEIGHT]
  drawBranches(canvas, location, 0, 100, 20)
  drawLeaves(canvas)
  drawGifts(canvas)
  drawStar(canvas)
// ...
const gifts = [' ', ' ', ' ', ' ', ' ', ' ', ' ']
function drawGifts(canvas) {
  const ctx = canvas.getContext('2d')
  ctx.save()
  ctx.font = '1.5rem sans-serif'
  for (let i = 0; i < 30; i++) {
    // 从树的像素点数组中随机获取位置
    const location = branchPixels[Math.floor(Math.random() * branchPixels.length)]
    const gift = gifts[i % gifts.length]
    ctx.fillText(gift, ...location)
  ctx.restore()
const image = new Image(500, 500)
image.src = 'star.png'
function drawStar(canvas) {
  const size = 50
  const ctx = canvas.getContext('2d')