-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
231 additions
and
53 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,55 +1,13 @@ | ||
import Bubble from './bubble'; | ||
|
||
export default class Canvas { | ||
constructor () { | ||
this.canvas = document.createElement('canvas'); | ||
this.canvas.innerText = | ||
'您的浏览器版本太低,请使用最新版本的 chrome、Firefox 或 edge 浏览器'; | ||
this.canvas.style.display = 'block'; | ||
this.canvas.style.background = '#000'; | ||
this.canvas.style.background = '#ccc'; | ||
document.body.appendChild(this.canvas); | ||
this.context = this.canvas.getContext('2d'); | ||
this.canvas.width = window.innerWidth; | ||
this.canvas.height = window.innerHeight; | ||
this.arr = []; // 存放鼠标移动产生的气泡 | ||
this.r = 50; // 默认气泡初始半径 | ||
this.colors = [ | ||
'#69d2e7', | ||
'#a7dbdb', | ||
'#3e0e4cc', | ||
'#f38630', | ||
'#fa6900', | ||
'#ff4e50', | ||
'#f9d423' | ||
]; // 设置一组比较好看的颜色 | ||
window.onresize = () => { | ||
// 实时根据视窗大小调整canvas大小 | ||
this.canvas.width = window.innerWidth; | ||
this.canvas.height = window.innerHeight; | ||
}; | ||
} | ||
|
||
// resize (canvas) { | ||
// canvas.width = window.innerWidth; | ||
// canvas.height = window.innerHeight; | ||
// } | ||
|
||
// 通过鼠标移动生成气泡 | ||
handler () { | ||
this.canvas.onmousemove = e => | ||
this.arr.push(new Bubble(e.offsetX, e.offsetY, this.r, this.colors)); | ||
this.render(); | ||
} | ||
render () { | ||
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height); // 清空给定矩形内的像素(x,y,宽,高) | ||
this.arr.forEach((item, i) => { | ||
item.draw(this.context); | ||
if (item.r === 0) { | ||
// 半径变成0时,删除气泡 | ||
this.arr.splice(i, 1); | ||
i--; // 由于删除了一个,索引要回拨1 | ||
} | ||
}); | ||
window.requestAnimationFrame(this.render.bind(this)); | ||
this.canvas.width = 500; | ||
this.canvas.height = 500; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,204 @@ | ||
import Canvas from './canvas'; | ||
|
||
window.onload = () => { | ||
const canvas = new Canvas(); | ||
canvas.handler(); | ||
let canvas = new Canvas(); | ||
let context = canvas.context; | ||
canvas.width = 500; | ||
canvas.height = 500; | ||
let CENTROID_RADIUS = 10, | ||
CENTROID_STROKE_STYLE = 'rgba(0,0,0,0.5)', | ||
CENTROID_FILL_STYLE = 'rgba(80,190,240,0.6)', | ||
RING_INNER_RADIUS = 35, | ||
RING_OUTER_RADIUS = 55, | ||
ANNOTATIONS_FILL_STYLE = 'rgba(0,0,230,0.9)', | ||
ANNOTATIONS_TEXT_SIZE = 12, | ||
TICK_WIDTH = 10, | ||
TICK_LONG_STROKE_STYLE = 'rgba(100,140,230,0.9)', | ||
TICK_SHORT_STROKE_STYLE = 'rgba(100,140,230,0.7)', | ||
TRACKING_DIAL_STROKING_STYLE = 'rgba(100,140,230,0.5)', | ||
GUIDEWIRE_STROKE_STYLE = 'goldenrod', | ||
GUIDEWIRE_FILL_STYLE = 'rgba(250,250,0,0.8)', | ||
circle = { | ||
x: canvas.width / 2, | ||
y: canvas.height / 2, | ||
radius: 150 | ||
}; | ||
|
||
function drawGrid (color, x, y) { | ||
context.save(); | ||
context.shadowColor = undefined; | ||
context.shadowOffsetX = 0; | ||
context.shadowOffsetY = 0; | ||
context.strokeStyle = color; | ||
context.fillStyle = '#fff'; | ||
context.lineWidth = 0.5; | ||
context.fillRect(0, 0, canvas.width, canvas.height); | ||
|
||
for (let i = x + 0.5; i < canvas.width; i += x) { | ||
context.beginPath(); | ||
context.moveTo(i, 0); | ||
context.lineTo(i, canvas.height); | ||
context.stroke(); | ||
} | ||
|
||
for (let i = y + 0.5; i < canvas.height; i += y) { | ||
context.beginPath(); | ||
context.moveTo(0, i); | ||
context.lineTo(canvas.width, i); | ||
context.stroke(); | ||
} | ||
context.restore(); | ||
} | ||
|
||
function draw () { | ||
let loc = { x: circle.x, y: circle.y }; | ||
drawCentroid(); | ||
drawCentroidGuidewire(loc); | ||
drawRing(); | ||
drawTickInnerCircle(); | ||
drawTicks(); | ||
drawAnnotations(); | ||
} | ||
|
||
function drawCentroid () { | ||
context.beginPath(); | ||
context.save(); | ||
context.strokeStyle = CENTROID_STROKE_STYLE; | ||
context.fillStyle = CENTROID_FILL_STYLE; | ||
context.arc(circle.x, circle.y, CENTROID_RADIUS, 0, Math.PI * 2, false); | ||
context.stroke(); | ||
context.fill(); | ||
context.restore(); | ||
} | ||
|
||
function drawCentroidGuidewire (loc) { | ||
let angle = -Math.PI / 4, | ||
radius, | ||
endpt; | ||
radius = circle.radius + RING_OUTER_RADIUS; | ||
if (loc.x >= circle.x) { | ||
endpt = { | ||
x: circle.x + radius * Math.cos(angle), | ||
y: circle.y + radius * Math.sign(angle) | ||
}; | ||
} else { | ||
endpt = { | ||
x: circle.x - radius * Math.cos(angle), | ||
y: circle.y - radius * Math.sin(angle) | ||
}; | ||
} | ||
context.save(); | ||
context.strokeStyle = GUIDEWIRE_STROKE_STYLE; | ||
context.fillStyle = GUIDEWIRE_FILL_STYLE; | ||
context.beginPath(); | ||
context.moveTo(circle.x, circle.y); | ||
context.lineTo(endpt.x, endpt.y); | ||
context.stroke(); | ||
context.beginPath(); | ||
context.strokeStyle = TICK_LONG_STROKE_STYLE; | ||
context.arc(endpt.x, endpt.y, 5, 0, Math.PI * 2, false); | ||
context.fill(); | ||
context.stroke(); | ||
context.restore(); | ||
} | ||
|
||
function drawRing () { | ||
drawRingOuterCircle(); | ||
context.strokeStyle = 'rgba(0,0,0,0.1)'; | ||
context.arc( | ||
circle.x, | ||
circle.y, | ||
circle.radius + RING_INNER_RADIUS, | ||
0, | ||
Math.PI * 2, | ||
false | ||
); | ||
context.fillStyle = 'rgba(100,140,230,0.1)'; | ||
context.fill(); | ||
context.stroke(); | ||
} | ||
|
||
function drawRingOuterCircle () { | ||
context.shadowColor = 'rgba(0,0,0,0.7)'; | ||
context.shadowOffsetX = 3; | ||
context.shadowOffsetY = 3; | ||
context.shadowBlur = 6; | ||
context.strokeStyle = TRACKING_DIAL_STROKING_STYLE; | ||
context.beginPath(); | ||
context.arc(circle.x, circle.y, circle.radius, 0, Math.PI * 2, true); | ||
context.stroke(); | ||
} | ||
|
||
function drawTickInnerCircle () { | ||
context.save(); | ||
context.beginPath(); | ||
context.strokeStyle = 'rgba(0,0,0,0.3)'; | ||
context.arc( | ||
circle.x, | ||
circle.y, | ||
circle.radius + RING_INNER_RADIUS - TICK_WIDTH, | ||
0, | ||
Math.PI * 2, | ||
false | ||
); | ||
context.stroke(); | ||
context.restore(); | ||
} | ||
|
||
function drawTick (angle, radius, cnt) { | ||
let tickWidth = cnt % 4 === 0 ? TICK_WIDTH : TICK_WIDTH / 2; | ||
|
||
context.beginPath(); | ||
context.moveTo( | ||
circle.x + Math.cos(angle) * (radius - tickWidth), | ||
circle.y + Math.sin(angle) * (radius - tickWidth) | ||
); | ||
context.lineTo( | ||
circle.x + Math.cos(angle) * radius, | ||
circle.y + Math.sin(angle) * radius | ||
); | ||
context.strokeStyle = TICK_SHORT_STROKE_STYLE; | ||
context.stroke(); | ||
} | ||
function drawTicks () { | ||
let radius = circle.radius + RING_INNER_RADIUS, | ||
ANGLE_MAX = 2 * Math.PI, | ||
ANGLE_DELTA = Math.PI / 64, | ||
tickWidth; | ||
context.save(); | ||
|
||
for ( | ||
let angle = 0, cnt = 0; | ||
angle < ANGLE_MAX; | ||
angle += ANGLE_DELTA, cnt++ | ||
) { | ||
drawTick(angle, radius, cnt++); | ||
} | ||
context.restore(); | ||
} | ||
|
||
function drawAnnotations () { | ||
let radius = circle.radius + RING_INNER_RADIUS; | ||
context.save(); | ||
context.fillStyle = ANNOTATIONS_FILL_STYLE; | ||
context.font = ANNOTATIONS_TEXT_SIZE + 'px sans-serif'; | ||
for (let angle = 0; angle < 2 * Math.PI; angle += Math.PI / 8) { | ||
context.beginPath(); | ||
context.fillText( | ||
((angle * 180) / Math.PI).toFixed(0), | ||
circle.x + Math.cos(angle) * (radius - TICK_WIDTH * 2), | ||
circle.y - Math.sin(angle) * (radius - TICK_WIDTH * 2) | ||
); | ||
} | ||
context.restore(); | ||
} | ||
|
||
context.shadowColor = 'rgba(0,0,0,0.4)'; | ||
context.shadowOffsetX = 2; | ||
context.shadowOffsetY = 2; | ||
context.shadowBlur = 4; | ||
context.textAlign = 'center'; | ||
context.textBaseline = 'middle'; | ||
drawGrid('lightgray', 10, 10); | ||
draw(); | ||
}; |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters