C:\Users\Administrator\PycharmProjects\untitled2\src\components\BookViewer3.vue

<template>
<div class="container">
<h6>可调整边长的直角三角形与内嵌矩形,注意:只要f跟bc在一条线上时, rectWidthRatio + rectHeightRatio=1,矩形面积是自己算吧</h6>
<div class="controls">
<div class="control-group">
<label>AB 边长 (水平边):</label>
<input type="number" v-model.number="abLength" min="100" max="400" step="10">
<span>{{ abLength }}px</span>
</div>
<div class="control-group">
<label>AC 边长 (垂直边):</label>
<input type="number" v-model.number="acLength" min="100" max="400" step="10">
<span>{{ acLength }}px</span>
</div>
<div class="control-group">
<label>矩形宽度比例 (AD/AB):</label>
<input type="number" v-model.number="rectWidthRatio" min="0.1" max="0.9" step="0.05">
<span>{{ rectWidthRatio }}</span>
</div>
<div class="control-group">
<label>矩形高度比例 (AE/AC):</label>
<input type="number" v-model.number="rectHeightRatio" min="0.1" max="0.9" step="0.05">
<span>{{ rectHeightRatio }}</span>
</div>
</div>
<div class="info-panel">
<div>三角形面积: {{ triangleArea.toFixed(1) }} px²</div>
<div>矩形面积: {{ rectangleArea.toFixed(1) }} px² ({{ areaPercentage }}%)</div>
<div>斜边 BC: {{ bcLength.toFixed(1) }} px</div>
</div>
<div class="canvas-wrapper">
<canvas ref="canvas" width="600" height="500"></canvas>
</div>
</div>
</template>
<script>
export default {
name: 'AdjustableRightTriangle',
data() {
return {
abLength: 300,
acLength: 250,
rectWidthRatio: 0.21,
rectHeightRatio: 0.79
};
},
computed: {
bcLength() {
return Math.sqrt(this.abLength ** 2 + this.acLength ** 2);
},
triangleArea() {
return (this.abLength * this.acLength) / 2;
},
adLength() {
return this.abLength * this.rectWidthRatio;
},
aeLength() {
return this.acLength * this.rectHeightRatio;
},
rectangleArea() {
return this.adLength * this.aeLength;
},
areaPercentage() {
return ((this.rectangleArea / this.triangleArea) * 100).toFixed(2);
},
points() {
const padding = 80;
const canvasHeight = 500;
return {
A: { x: padding, y: canvasHeight - padding },
B: { x: padding + this.abLength, y: canvasHeight - padding },
C: { x: padding, y: canvasHeight - padding - this.acLength },
D: { x: padding + this.adLength, y: canvasHeight - padding },
E: { x: padding, y: canvasHeight - padding - this.aeLength },
F: { x: padding + this.adLength, y: canvasHeight - padding - this.aeLength }
};
}
},
mounted() {
this.draw();
},
watch: {
abLength() { this.draw(); },
acLength() { this.draw(); },
rectWidthRatio() { this.draw(); },
rectHeightRatio() { this.draw(); }
},
methods: {
draw() {
const canvas = this.$refs.canvas;
const ctx = canvas.getContext('2d');
const { A, B, C, D, E, F } = this.points;
// 清空画布
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 绘制网格
this.drawGrid(ctx);
// 绘制三角形
ctx.beginPath();
ctx.moveTo(A.x, A.y);
ctx.lineTo(B.x, B.y);
ctx.lineTo(C.x, C.y);
ctx.closePath();
ctx.fillStyle = 'rgba(52, 152, 219, 0.2)';
ctx.fill();
ctx.strokeStyle = '#2980b9';
ctx.lineWidth = 3;
ctx.stroke();
// 绘制矩形
ctx.beginPath();
ctx.moveTo(A.x, A.y);
ctx.lineTo(D.x, D.y);
ctx.lineTo(F.x, F.y);
ctx.lineTo(E.x, E.y);
ctx.closePath();
ctx.fillStyle = 'rgba(231, 76, 60, 0.4)';
ctx.fill();
ctx.strokeStyle = '#c0392b';
ctx.lineWidth = 2;
ctx.stroke();
// 绘制点和标签
this.drawPoints(ctx, [A, B, C, D, E, F], ['A', 'B', 'C', 'D', 'E', 'F']);
// 绘制尺寸标注
this.drawDimensions(ctx, A, B, C, D, E, F);
},
drawGrid(ctx) {
ctx.strokeStyle = '#f0f0f0';
ctx.lineWidth = 1;
for (let x = 0; x <= 600; x += 25) {
ctx.beginPath();
ctx.moveTo(x, 0);
ctx.lineTo(x, 500);
ctx.stroke();
}
for (let y = 0; y <= 500; y += 25) {
ctx.beginPath();
ctx.moveTo(0, y);
ctx.lineTo(600, y);
ctx.stroke();
}
},
drawPoints(ctx, points, labels) {
points.forEach((point, index) => {
ctx.beginPath();
ctx.arc(point.x, point.y, 6, 0, Math.PI * 2);
ctx.fillStyle = '#27ae60';
ctx.fill();
ctx.font = 'bold 18px Arial';
ctx.fillStyle = '#2c3e50';
ctx.textAlign = 'center';
ctx.fillText(labels[index], point.x, point.y - 20);
});
},
drawDimensions(ctx, A, B, C, D, E, F) {
// 简化标注函数
const drawLine = (p1, p2, text) => {
ctx.beginPath();
ctx.moveTo(p1.x, p1.y);
ctx.lineTo(p2.x, p2.y);
ctx.strokeStyle = '#7f8c8d';
ctx.setLineDash([5, 3]);
ctx.stroke();
ctx.fillStyle = '#7f8c8d';
ctx.font = '14px Arial';
ctx.fillText(text, (p1.x + p2.x) / 2, (p1.y + p2.y) / 2 - 10);
};
drawLine(A, B, `AB: ${this.abLength}px`);
drawLine(A, C, `AC: ${this.acLength}px`);
drawLine(B, C, `BC: ${this.bcLength.toFixed(1)}px`);
drawLine(A, D, `AD: ${this.adLength.toFixed(1)}px`);
drawLine(A, E, `AE: ${this.aeLength.toFixed(1)}px`);
}
}
};
</script>
<style scoped>
.container {
font-family: Arial, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
.controls {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 15px;
margin-bottom: 20px;
background: #f8f9fa;
padding: 20px;
border-radius: 8px;
}
.control-group {
display: flex;
flex-direction: column;
gap: 5px;
}
.control-group label {
font-weight: bold;
color: #333;
}
.control-group input {
padding: 8px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 16px;
}
.info-panel {
display: flex;
justify-content: space-around;
background: #e8f4fc;
padding: 15px;
border-radius: 8px;
margin-bottom: 20px;
font-weight: bold;
}
.canvas-wrapper {
border: 1px solid #ddd;
border-radius: 8px;
overflow: hidden;
}
</style>
332

被折叠的 条评论
为什么被折叠?



