按钮

文本按钮

这个示例实现了一个 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]]);
});