基于konvajs进行实现,一个强大的canvas库,进行了组件化,支持原生js、react、vue.
https://konvajs.org/docs/react/Custom_Shape.html
先上效果图:
import React, { Component } from "react";
import Konva from 'konva';
import { render } from "react-dom";
import { Stage, Layer, Text, Circle, Shape, Line } from "react-konva";
class App extends Component {
state = {
iamge: null,
// 设置图片的自适应缩放,以0.55为缩放基准,所以原图大小除以1.8
fillPatternScale: 0
};
componentDidMount() {
this.im();
}
im = () => {
this.image = new Image();
this.image.src = "https://konvajs.org/assets/lion.png";
this.image.addEventListener("load", this.handleLoad);
};
handleLoad = () => {
console.log(this.image);
// after setState react-konva will update canvas and redraw the layer
// because "image" property is changed
this.setState({
image: this.image,
fillPatternScale: (this.image.width/1.8) / this.image.width
});
// if you keep same image object during source updates
// you will have to update layer manually:
// this.imageNode.getLayer().batchDraw();
};
render() {
const { image,fillPatternScale } = this.state;
let xx = [];
return (
<Stage width={window.innerWidth} height={window.innerHeight}>
<Layer>
<Line
points={xx}
stroke="green"
lineJoin="round"
lineCap="round"
dash={[8, 10, 0.001, 10]}
/>
{[
{ x: 100, y: 200, startTime: 1 },
{ x: 200, y: 100, startTime: 2 },
{ x: 300, y: 200, startTime: 3 }
].map(item => {
xx.push(item.x, item.y + 45);
return [
<Shape
x={item.x}
y={item.y}
sceneFunc={(context, shape) => {
context.beginPath();
context.arc(0, 0, 20, 0.75 * Math.PI, 0.25 * Math.PI);
context.lineTo(0, 30);
context.closePath();
// (!) Konva specific method, it is very important
context.fillStrokeShape(shape);
}}
stroke="blue"
strokeWidth={2}
fillPatternImage={image}
fillPatternRepeat="no-repeat"
// 设置偏移量
fillPatternOffsetX={85}
fillPatternOffsetY={50}
// 设置图片自缩放
fillPatternScaleX={fillPatternScale}
fillPatternScaleY={fillPatternScale}
/>,
<Text
text={item.startTime}
fontFamily={"宋体"}
x={item.x - 4}
y={item.y + 60}
fontSize={15}
stroke="blue"
/>,
<Circle
x={item.x}
y={item.y + 45}
radius={4}
strokeWidth={3}
fill={"white"}
stroke="#09D3EF"
/>
];
})}
</Layer>
</Stage>
);
}
}
render(<App />, document.getElementById("root"));