Commit d66653db authored by hucy's avatar hucy

canvas绘制函数曲线

parent ff6945a3
......@@ -12,7 +12,8 @@ export default {
// import MorphBox from './element/MorphBox.vue';
// import CarouselWarp from './element/CarouselWarp.vue';
// import DataResponsive from './element/DataResponsive.vue';
import CanvasStudy from './element/CanvasStudy.vue';
// import CanvasStudy from './element/CanvasStudyCopy1.vue';
import CanvasStudy from './element/CanvasCurve.vue';
</script>
<template>
<div class="page6 container-height">
......
<!--
* canvas 曲线
-->
<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue';
import { drawGrid, rotateOriginOffset, toArc } from '../utils';
const center = {
x: 200,
y: 300,
};
const step = ref(0);
const translateX = ref(0);
const translateXstep = ref(0);
const isShowGrid = ref(false);
const state = reactive({
gridDom: null as any,
canvasDom: null as any,
curveDom: null as any,
r: 100,
r2: 40,
});
onMounted(() => {
state.canvasDom = document.getElementById('canvas');
state.gridDom = document.getElementById('canvas-grid');
state.curveDom = document.getElementById('canvas-curve');
initCanvas();
});
function initCanvas() {
const { r } = state;
let ctx = state.canvasDom.getContext('2d');
let pen = state.curveDom.getContext('2d');
translateXstep.value = (r - Math.cos(toArc(30)) * r) / 60;
window.requestAnimationFrame(() => {
draw(ctx, r, pen);
});
}
function draw(ctx: any, r: number, pen: any) {
// 基础圆
ctx.save();
ctx.clearRect(0, 0, 1200, 600);
ctx.beginPath();
ctx.arc(center.x, center.y, r, 0, 2 * Math.PI);
ctx.lineWidth = 1;
ctx.strokeStyle = '#78C0A8';
ctx.stroke();
ctx.restore();
ctx.save();
// 每次走0.5度,1秒钟走30度,
const arc = toArc(360 - step.value * 0.5);
// const arc = toArc(30);
const offset1 = rotateOriginOffset(1200, center, arc);
ctx.translate(offset1.x, offset1.y); // 改变旋转中心
ctx.rotate(arc);
ctx.beginPath();
ctx.moveTo(center.x, center.y);
ctx.lineTo(center.x + r, center.y);
ctx.lineWidth = 2;
ctx.strokeStyle = '#78C0A8';
ctx.stroke();
// 第二个圆
const centerX2 = center.x + r; // 第2个圆的圆心
const centerY2 = center.y;
ctx.beginPath();
ctx.arc(centerX2, centerY2, 4, 0, Math.PI * 2);
ctx.strokeStyle = '#FC4422';
ctx.stroke();
ctx.restore();
// 圆弧上点的坐标
const a = Math.sin(arc) * r;
const b = Math.cos(arc) * r;
const x0 = center.x + b;
const y0 = center.y + a;
const lastX = center.x + r + 100;
ctx.save();
ctx.beginPath();
ctx.moveTo(x0, y0);
ctx.lineTo(lastX, y0);
ctx.strokeStyle = '#78C0A8';
ctx.stroke();
ctx.restore();
// 曲线画布
translateX.value += translateXstep.value; // 每次平移的值
pen.save();
pen.beginPath();
pen.arc(lastX - translateX.value, y0, 2, 0, Math.PI * 2);
pen.fillStyle = '#78C0A8';
pen.fill();
pen.restore();
step.value++;
// 回调函数执行次数通常是每秒 60 次
// if (step.value < 60) {
// window.requestAnimationFrame(() => {
// draw(ctx, r, pen);
// });
// }
if (translateX.value > 400) {
translateX.value = 0;
pen.clearRect(0, 0, 1200, 600);
}
if (step.value === 60 * 12) {
step.value = 0;
}
window.requestAnimationFrame(() => {
draw(ctx, r, pen);
});
}
function showGrid() {
let ctx = state.gridDom.getContext('2d');
isShowGrid.value = !isShowGrid.value;
if (isShowGrid.value) {
drawGrid('red', 1200, 600, ctx);
} else {
ctx.clearRect(0, 0, 1200, 600);
}
}
</script>
<template>
<div class="fit">
<div class="title">canvas 曲线</div>
<div class="btns">
<q-btn label="网格" color="primary" @click="showGrid" />
</div>
<div class="relative-position">
<canvas
id="canvas"
width="1200"
height="600"
style="border: 1px solid red; position: absolute; top: 0; left: 0"
></canvas>
<canvas
id="canvas-curve"
width="1200"
height="600"
:style="{
border: '1px solid transparent',
position: 'absolute',
top: 0,
left: 0,
transform: `translate(${translateX}px, 0)`,
}"
></canvas>
<canvas
id="canvas-grid"
width="1200"
height="600"
style="
border: 1px solid transparent;
position: absolute;
top: 0;
left: 0;
"
></canvas>
</div>
</div>
</template>
<style lang="scss" scoped>
.title {
margin-bottom: $padding-md;
}
.btns {
margin-bottom: $padding-md;
}
</style>
<!--
* canvas学习
* canvas 时钟
-->
<script setup lang="ts">
import { onMounted, ref, reactive, onBeforeUnmount } from 'vue';
......
......@@ -123,24 +123,24 @@ function sineCurve() {
};
}
// let i = 24;
// setInterval(() => {
// if (i < 0) {
// i = 23;
// }
// drawArc((i * 15 * Math.PI) / 180);
// i--;
// if (transX.value > 300) {
// transX.value = 0;
// pen2.clearRect(0, 0, 1200, 600);
// }
// }, 1000);
drawArc((360 * Math.PI) / 180);
drawArc((345 * Math.PI) / 180);
drawArc((330 * Math.PI) / 180);
drawArc((315 * Math.PI) / 180);
drawArc((300 * Math.PI) / 180);
let i = 24;
setInterval(() => {
if (i < 0) {
i = 23;
}
drawArc((i * 15 * Math.PI) / 180);
i--;
if (transX.value > 300) {
transX.value = 0;
pen2.clearRect(0, 0, 1200, 600);
}
}, 1000);
// drawArc((360 * Math.PI) / 180);
// drawArc((345 * Math.PI) / 180);
// drawArc((330 * Math.PI) / 180);
// drawArc((315 * Math.PI) / 180);
// drawArc((300 * Math.PI) / 180);
// drawArc((285 * Math.PI) / 180);
// drawArc((270 * Math.PI) / 180);
// drawArc((255 * Math.PI) / 180);
......
/**
* 绘制网格
* @param color 网格颜色
* @param w canvas画布宽
* @param h canvas画布高
* @param pen canvas 画笔
* @param status 默认true,保存画布状态
*/
export function drawGrid(
color: string,
w: number,
h: number,
pen: any,
status = true
) {
const step = 100;
const w_l = w / step;
const h_l = h / step;
if (status) {
pen.save();
}
// 横着的线
for (let i = 0; i <= h_l; i++) {
pen.beginPath();
pen.strokeStyle = color;
pen.moveTo(0, i * step);
pen.lineTo(w, i * step);
pen.stroke();
}
// 竖着的线
for (let i = 0; i <= w_l; i++) {
pen.beginPath();
pen.moveTo(i * step, 0);
pen.lineTo(i * step, h);
pen.stroke();
}
if (status) {
pen.restore();
}
}
/**
* canvas旋转中心偏移值
* @param width canvas宽
* @param center 中心坐标点 center:{x:100,y:100}
* @param arc 旋转的弧度值
*/
export function rotateOriginOffset(
width: number,
center: { x: number; y: number },
arc: any
) {
const r1 = width - center.x;
const xRes1 = Math.cos(arc) * r1;
const yRes1 = Math.sin(arc) * r1;
const x1 = center.x + xRes1;
const y1 = center.y + yRes1;
const x0 = width;
const y0 = center.y;
const c0 = Math.sqrt(Math.pow(x0, 2) + Math.pow(y0, 2));
const arc0 = Math.atan2(y0, x0);
const arc_0 = arc0 + arc;
const y2 = Math.sin(arc_0) * c0;
const x2 = y2 / Math.tan(arc_0);
const xLength = x1 - x2;
const yLength = y1 - y2;
return {
x: xLength,
y: yLength,
};
}
/**
* 角度值转弧度值
* @param degree 角度值
*/
export function toArc(degree: number) {
return (degree * Math.PI) / 180;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment