Kros的博客 Kros的博客
首页
  • CSS
  • 工具
  • Vue
  • js
  • Vue3
  • 算法
  • 折腾笔记
一言
  • 分类
  • 标签
  • 归档
码云

Kros

凡心所向,素履以往,生如逆旅,一苇以航
首页
  • CSS
  • 工具
  • Vue
  • js
  • Vue3
  • 算法
  • 折腾笔记
一言
  • 分类
  • 标签
  • 归档
码云
  • CSS

  • JavaScript

  • 工具

  • Vue

    • vue批量引入组件
    • vue中watch用法
    • vue使用基础JSX语法
    • vue首页白屏
    • vue长列表优化
    • 模板文件中script、template、style存在必要性
    • popup弹窗组件
    • 使用$mount和extend扩展vue
    • 扩展toast合并popup(按需加载)
    • canvas实现弧形进度条
    • vue中使用CSS Modules
    • vue实现无限轮播图
    • vue半圆形菜单
    • 纯CSS实现圆形进度条
    • v-model简单实现
    • vue带箭头下拉框
    • vue事件修饰符
    • vue鼠标悬浮显示提示文字
    • vue添加发布版本号方法
    • vue配置全局样式文件
    • vue在env development中设置全局变量不生效
    • vue引入less或scss全局变量
    • vue中使用Keepalive
    • vue2为什么只支持一个根节点
    • vue打包优化分析工具—webpack-bundle-analyzer
    • vue使用echarts(按需加载)
    • echarts柱形图重合堆叠
    • vue使用draggable实现多列拖拽(解决空列不能拖拽问题)
    • vue禁止三方库打包到bundle中
    • npm run serve运行背后的思考
    • vxe-table树结构不允许insert
    • vue组件延迟加载
    • 多页面应用配置
    • vue项目常用优化
    • vue实现拖动拼图验证码
    • vue虚拟dom
    • canvas心形动画
    • canvas绘制玫瑰曲线
    • element表单validateField验证部分字段
    • element日期选择限制今天以后并精确到小时
    • 前端使用JSEncrypt和node-rsa进行rsa加密传输和接收解密
    • elementui日期选择器生日只选择月和日不选择年并隐藏年份
    • el-upload组件第二次点击手动submit时不生效
    • element表单内输入框使用@keyup enter native回车时会刷新页面
  • antdv踩坑记录

  • Vue3

  • 前端
  • Vue
kros
2021-06-22

canvas心形动画

# 方程式

x = 16(sinθ)^3
y = 13cosθ - 5cos2θ - 2cos3θ - cos4θ
1
2

θ闭环为2π

# 具体实现

按照上面笛卡尔坐标,转化绘制代码如下,我们把坐标x、y同时放大15倍,并将图像翻转

function getX1(t){  //获取心型线的X坐标
	// 放大x轴15倍
	return 15*(16*Math.pow(Math.sin(t),3))
}

function getY1(t){  //获取心型线的Y坐标
	// 设置-15放大15倍的同事反转y轴
	return -15*(13*Math.cos(t)-5*Math.cos(2*t)-2*Math.cos(3*t)-Math.cos(4*t))
}
1
2
3
4
5
6
7
8
9

绘制代码如下:

<canvas ref="drawing" width="500" height="500"></canvas>
1
function draw(){
	var drawing = document.getElementById("drawing"); //获取canvas元素
	drawing.width = '500'; //设置画布大小
	drawing.height = '500';
	if (drawing.getContext){  //获取绘图上下文
		var content = drawing.getContext("2d"),
			radian = 0,   //设置初始弧度
			radian_add = Math.PI/30;  //设置弧度增量
		// 清空画板
		content.clearRect(0, 0, canvas.width, canvas.height)
		content.beginPath();  //开始绘图
		content.translate(250,250);  //设置绘图原点
		content.moveTo(getX(radian),getY(radian)); //移动绘图游标至原点
		while(radian <= (Math.PI*2)){  //每增加一次弧度,绘制一条线
			radian += radian_add;
			X = getX1(radian);
			Y = getY1(radian);
			// X = getX2(radian);
			// Y = getY2(radian);
			content.lineTo(X,Y);
		}
		content.strokeStyle = "red";  //设置描边样式
		content.stroke();  //对路径描边
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# 动态绘制

上述代码为静态一次绘制,实际场景中需要逐点动态绘制,这里我们借助requestAnimationFrame 方法实现逐帧绘制坐标点 同理使用setTimeout亦可实现动态效果

function draw {
  if (!drawing.value) return
  const canvas = drawing.value
  canvas.width = 500
  canvas.height = 500
  const content = canvas.getContext('2d')
  if (content) {
    content.clearRect(0, 0, canvas.width, canvas.height)
    let radian = 0
    const radian_add = Math.PI / 180
    content.beginPath()
    content.translate(250 + getX1(radian), 250 + getY1(radian))
    content.strokeStyle = 'red'
    let timer: number
    const lineFunc = () => {
      if (radian <= Math.PI * 2) {
        const X = getX1(radian)
        const Y = getY1(radian)
        content.lineTo(X, Y)
        content.stroke()
        radian += radian_add
        timer = requestAnimationFrame(lineFunc)
      } else {
        cancelAnimationFrame(timer)
      }
    }
    lineFunc()
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

效果如下:

demo

上次更新: 2025/09/05, 8:09:00
vue虚拟dom
canvas绘制玫瑰曲线

← vue虚拟dom canvas绘制玫瑰曲线→

最近更新
01
Find the next perfect square
09-05
02
Regex validate PIN code
09-05
03
Find the odd int
09-05
更多文章>
Theme by Vdoing | Copyright © 2020-2025 kros king
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
icon-heart-o icon-heart icon-infinity icon-pause icon-play link next prev