这个示例实现了一个 material ui 风格的按钮组件。
按钮的大小会随着文本长度自动缩放。
你可以暴露更多的参数,比如 padding 来改变按钮的样式。
export function TextButton(x: number, y: number, { radius, styles, text, textBoundingBox, onClick }: TextButtonProps): ShadowElement {
if (!radius) radius = 0;
const textOpts: TextOptions = {
textAlign: "center",
textBaseline: "middle",
fill: styles.normal.textColor,
};
if (styles.common.font && styles.common.textLineHeight) {
textOpts.font = styles.common.font;
textOpts.lineHeight = styles.common.textLineHeight;
}
const buttonText = {
content: text,
opts: textOpts,
};
const bb = textBoundingBox(buttonText);
const width = bb.width + 36;
const height = bb.height + 24;
const contain = rectContain(width, height, false);
return {
x,
y,
shapes: shapes({ width, height, radius }, styles.normal),
contain,
texts: [buttonText],
data: { animation: newAnimationStore(styles.normal) },
update(ts: number) {
if (animationRunning(this.data.animation)) {
const result = updateAnimation<TextButtonStyles>(this.data.animation, ts);
applyStyle(this.shapes, result);
this.texts![0].opts!.fill = result.textColor;
}
},
onMouseenter() {
startAnimation(this.data.animation, 250, styles.active);
},
onMouseleave() {
startAnimation(this.data.animation, 250, styles.normal);
},
onClick,
};
}
// Since we hope the size of button should scale automatically,
// we can get the size of text in canvas only if our canvas are ready (canvas created in the browser, and worker are ready if we use web worker).
// Different devices could run faster or slower, it commonly takes less than 10 ms to prepare a new canvas in the web worker thread.
// Therefore, you can't build this text button before the graph started.
graph.onReady(() => {
// to create a new button here
const btn = TextButton(240, 180, { text: "click me", radius: 8, styles, textBoundingBox: graph.boundingBox.bind(graph) });
graph.updateLayerOptions(0, { dynamic: true, update: true });
graph.resetGraph([[btn]]);
});