Skip to content

使用示例

本节提供了 tui-entine 的一些使用示例,帮助你快速上手。

基础布局示例

简单页面布局

ts
import { TuiEngine } from "@/uni_modules/tui-entine";
import { ITuiEngine } from "@/uni_modules/tui-entine/types";

let eng: ITuiEngine | null = null;

function initFinished(engine: ITuiEngine) {
  eng = engine;

  // 创建根容器
  const root = engine.createView();
  root.style.width = engine.width;
  root.style.height = engine.height;
  root.style.backgroundColor = "#ffffff";
  root.style.padding = 20;

  // 创建标题
  const title = engine.createText();
  title.value = "欢迎使用 tui-entine";
  title.style.fontSize = 24;
  title.style.color = "#333333";
  title.style.marginBottom = 20;

  // 创建内容容器
  const content = engine.createView();
  content.style.flexDirection = "column";
  content.style.flex = 1;

  // 创建按钮
  const button = engine.createButton();
  button.value = "点击我";
  button.style.width = 200;
  button.style.height = 44;
  button.style.backgroundColor = "#2979ff";
  button.style.color = "#ffffff";
  button.style.borderRadius = 8;
  button.style.marginTop = 20;

  // 添加点击事件
  button.addEventListener("click", (event) => {
    console.log("按钮被点击");
  });

  // 组装元素树
  content.appendChild(title, button);
  root.appendChild(content);

  // 绘制
  engine.draw(root, null);
}

function touchstart(e: any) {
  if (eng) {
    eng.handleTouchEvent(e);
  }
}

function touchmove(e: any) {
  if (eng) {
    eng.handleTouchEvent(e);
  }
}

function touchend(e: any) {
  if (eng) {
    eng.handleTouchEvent(e);
  }
}

水平布局

ts
function createHorizontalLayout(engine: ITuiEngine) {
  const root = engine.createView();
  root.style.width = engine.width;
  root.style.height = engine.height;
  root.style.backgroundColor = "#f5f5f5";
  root.style.padding = 20;

  // 水平容器
  const container = engine.createView();
  container.style.display = "flex";
  container.style.flexDirection = "row";
  container.style.gap = 10;

  // 创建三个子元素
  for (let i = 0; i < 3; i++) {
    const item = engine.createView();
    item.style.flex = 1;
    item.style.height = 100;
    item.style.backgroundColor = `#${(i * 50).toString(16).padStart(2, "0")}99ff`;
    item.style.borderRadius = 8;
    item.style.justifyContent = "center";
    item.style.alignItems = "center";

    const text = engine.createText();
    text.value = `项目 ${i + 1}`;
    text.style.color = "#ffffff";
    text.style.fontSize = 16;

    item.appendChild(text);
    container.appendChild(item);
  }

  root.appendChild(container);
  engine.draw(root, null);
}

垂直布局

ts
function createVerticalLayout(engine: ITuiEngine) {
  const root = engine.createView();
  root.style.width = engine.width;
  root.style.height = engine.height;
  root.style.backgroundColor = "#f5f5f5";
  root.style.padding = 20;

  // 垂直容器
  const container = engine.createView();
  container.style.display = "flex";
  container.style.flexDirection = "column";
  container.style.gap = 10;

  // 创建三个子元素
  for (let i = 0; i < 3; i++) {
    const item = engine.createView();
    item.style.width = "100%";
    item.style.flex = 1;
    item.style.backgroundColor = `#ff${(i * 50).toString(16).padStart(2, "0")}99`;
    item.style.borderRadius = 8;
    item.style.justifyContent = "center";
    item.style.alignItems = "center";

    const text = engine.createText();
    text.value = `项目 ${i + 1}`;
    text.style.color = "#ffffff";
    text.style.fontSize = 16;

    item.appendChild(text);
    container.appendChild(item);
  }

  root.appendChild(container);
  engine.draw(root, null);
}

动态更新示例

元素移动

ts
let element: any = null;
let offsetX = 0;
let offsetY = 0;

function createMovableElement(engine: ITuiEngine) {
  const root = engine.createView();
  root.style.width = engine.width;
  root.style.height = engine.height;
  root.style.backgroundColor = "#ffffff";

  // 创建可移动的元素
  element = engine.createView();
  element.style.width = 100;
  element.style.height = 100;
  element.style.backgroundColor = "#2979ff";
  element.style.borderRadius = 8;
  element.style.position = "absolute";
  element.style.left = 50;
  element.style.top = 50;

  // 添加触摸事件
  element.addEventListener("touchstart", (event: any) => {
    const rect = element.getBoundingClientRect();
    offsetX = event.clientX - rect.x;
    offsetY = event.clientY - rect.y;
  });

  element.addEventListener("touchmove", (event: any) => {
    element.style.left = event.clientX - offsetX;
    element.style.top = event.clientY - offsetY;
    engine.updateElement(element, true);
  });

  root.appendChild(element);
  engine.draw(root, null);
}

颜色变化

ts
function createColorChangingElement(engine: ITuiEngine) {
  const root = engine.createView();
  root.style.width = engine.width;
  root.style.height = engine.height;
  root.style.backgroundColor = "#ffffff";
  root.style.justifyContent = "center";
  root.style.alignItems = "center";

  // 创建颜色变化的元素
  const element = engine.createView();
  element.style.width = 200;
  element.style.height = 200;
  element.style.backgroundColor = "#2979ff";
  element.style.borderRadius = 100;

  // 添加点击事件
  element.addEventListener("click", () => {
    // 生成随机颜色
    const color = `#${Math.floor(Math.random() * 16777215)
      .toString(16)
      .padStart(6, "0")}`;
    element.style.backgroundColor = color;
    engine.updateElement(element, false);
  });

  root.appendChild(element);
  engine.draw(root, null);
}

文本更新

ts
function createDynamicText(engine: ITuiEngine) {
  const root = engine.createView();
  root.style.width = engine.width;
  root.style.height = engine.height;
  root.style.backgroundColor = "#ffffff";
  root.style.justifyContent = "center";
  root.style.alignItems = "center";

  // 创建文本元素
  const text = engine.createText();
  text.value = "点击更新文本";
  text.style.fontSize = 20;
  text.style.color = "#333333";

  // 添加点击事件
  text.addEventListener("click", () => {
    text.value = `更新时间: ${new Date().toLocaleTimeString()}`;
    engine.updateElement(text, true);
  });

  root.appendChild(text);
  engine.draw(root, null);
}

复杂布局示例

卡片布局

ts
function createCardLayout(engine: ITuiEngine) {
  const root = engine.createView();
  root.style.width = engine.width;
  root.style.height = engine.height;
  root.style.backgroundColor = "#f5f5f5";
  root.style.padding = 20;

  // 创建多个卡片
  for (let i = 0; i < 3; i++) {
    const card = engine.createView();
    card.style.width = "100%";
    card.style.backgroundColor = "#ffffff";
    card.style.borderRadius = 8;
    card.style.padding = 15;
    card.style.marginBottom = 15;
    card.style.shadow = "0 2px 8px rgba(0,0,0,0.1)";

    // 卡片标题
    const title = engine.createText();
    title.value = `卡片 ${i + 1}`;
    title.style.fontSize = 18;
    title.style.color = "#333333";
    title.style.marginBottom = 10;

    // 卡片内容
    const content = engine.createText();
    content.value = "这是卡片内容,包含一些描述性文本。";
    content.style.fontSize = 14;
    content.style.color = "#666666";
    content.style.lineHeight = 1.5;

    // 卡片按钮
    const button = engine.createView();
    button.style.width = 80;
    button.style.height = 32;
    button.style.backgroundColor = "#2979ff";
    button.style.borderRadius = 16;
    button.style.justifyContent = "center";
    button.style.alignItems = "center";
    button.style.marginTop = 15;

    const buttonText = engine.createText();
    buttonText.value = "查看";
    buttonText.style.fontSize = 12;
    buttonText.style.color = "#ffffff";

    button.appendChild(buttonText);
    card.appendChild(title, content, button);
    root.appendChild(card);
  }

  engine.draw(root, null);
}

响应式布局

ts
function createResponsiveLayout(engine: ITuiEngine) {
  const root = engine.createView();
  root.style.width = engine.width;
  root.style.height = engine.height;
  root.style.backgroundColor = "#ffffff";
  root.style.padding = 20;

  // 响应式容器
  const container = engine.createView();
  container.style.display = "flex";
  container.style.flexWrap = "wrap";
  container.style.gap = 10;

  // 创建多个项目
  for (let i = 0; i < 6; i++) {
    const item = engine.createView();
    // 响应式宽度
    item.style.width = `${(engine.width - 50) / 2}px`;
    item.style.height = 100;
    item.style.backgroundColor = `#${(i * 30).toString(16).padStart(2, "0")}ccff`;
    item.style.borderRadius = 8;
    item.style.justifyContent = "center";
    item.style.alignItems = "center";

    const text = engine.createText();
    text.value = `项目 ${i + 1}`;
    text.style.color = "#ffffff";

    item.appendChild(text);
    container.appendChild(item);
  }

  root.appendChild(container);
  engine.draw(root, null);
}

表单布局

ts
function createFormLayout(engine: ITuiEngine) {
  const root = engine.createView();
  root.style.width = engine.width;
  root.style.height = engine.height;
  root.style.backgroundColor = "#ffffff";
  root.style.padding = 20;

  // 表单容器
  const form = engine.createView();
  form.style.display = "flex";
  form.style.flexDirection = "column";
  form.style.gap = 15;

  // 输入框容器
  function createInput(labelText: string) {
    const container = engine.createView();
    container.style.display = "flex";
    container.style.flexDirection = "column";
    container.style.gap = 5;

    const label = engine.createText();
    label.value = labelText;
    label.style.fontSize = 14;
    label.style.color = "#666666";

    const input = engine.createView();
    input.style.height = 44;
    input.style.borderWidth = 1;
    input.style.borderColor = "#e0e0e0";
    input.style.borderRadius = 8;
    input.style.paddingLeft = 12;
    input.style.paddingRight = 12;
    input.style.backgroundColor = "#f9f9f9";

    container.appendChild(label, input);
    return container;
  }

  // 创建表单元素
  form.appendChild(
    createInput("用户名"),
    createInput("密码"),
    createInput("邮箱"),
  );

  // 提交按钮
  const submitButton = engine.createView();
  submitButton.style.height = 48;
  submitButton.style.backgroundColor = "#2979ff";
  submitButton.style.borderRadius = 8;
  submitButton.style.justifyContent = "center";
  submitButton.style.alignItems = "center";
  submitButton.style.marginTop = 20;

  const buttonText = engine.createText();
  buttonText.value = "提交";
  buttonText.style.fontSize = 16;
  buttonText.style.color = "#ffffff";

  submitButton.appendChild(buttonText);
  form.appendChild(submitButton);

  root.appendChild(form);
  engine.draw(root, null);
}

交互示例

拖拽示例

ts
function createDraggableElement(engine: ITuiEngine) {
  const root = engine.createView();
  root.style.width = engine.width;
  root.style.height = engine.height;
  root.style.backgroundColor = "#f5f5f5";

  // 创建拖拽元素
  const draggable = engine.createView();
  draggable.style.width = 100;
  draggable.style.height = 100;
  draggable.style.backgroundColor = "#2979ff";
  draggable.style.borderRadius = 8;
  draggable.style.position = "absolute";
  draggable.style.left = 50;
  draggable.style.top = 50;

  let isDragging = false;
  let startX = 0;
  let startY = 0;
  let offsetX = 0;
  let offsetY = 0;

  // 触摸开始
  draggable.addEventListener("touchstart", (event: any) => {
    isDragging = true;
    startX = event.clientX;
    startY = event.clientY;
    const rect = draggable.getBoundingClientRect();
    offsetX = startX - rect.x;
    offsetY = startY - rect.y;
  });

  // 触摸移动
  draggable.addEventListener("touchmove", (event: any) => {
    if (isDragging) {
      const newX = event.clientX - offsetX;
      const newY = event.clientY - offsetY;

      // 限制在边界内
      const maxX = engine.width - draggable.style.width;
      const maxY = engine.height - draggable.style.height;

      draggable.style.left = Math.max(0, Math.min(newX, maxX));
      draggable.style.top = Math.max(0, Math.min(newY, maxY));

      engine.updateElement(draggable, true);
    }
  });

  // 触摸结束
  draggable.addEventListener("touchend", () => {
    isDragging = false;
  });

  root.appendChild(draggable);
  engine.draw(root, null);
}

点击反馈

ts
function createButtonWithFeedback(engine: ITuiEngine) {
  const root = engine.createView();
  root.style.width = engine.width;
  root.style.height = engine.height;
  root.style.backgroundColor = "#ffffff";
  root.style.justifyContent = "center";
  root.style.alignItems = "center";

  // 创建按钮
  const button = engine.createView();
  button.style.width = 160;
  button.style.height = 48;
  button.style.backgroundColor = "#2979ff";
  button.style.borderRadius = 24;
  button.style.justifyContent = "center";
  button.style.alignItems = "center";

  const buttonText = engine.createText();
  buttonText.value = "点击我";
  buttonText.style.fontSize = 16;
  buttonText.style.color = "#ffffff";

  button.appendChild(buttonText);

  // 添加点击事件
  button.addEventListener("touchstart", () => {
    // 按下效果
    button.style.transform = {
      scaleX: 0.95,
      scaleY: 0.95,
    };
    engine.updateElement(button, true);
  });

  button.addEventListener("touchend", () => {
    // 释放效果
    button.style.transform = {
      scaleX: 1,
      scaleY: 1,
    };
    engine.updateElement(button, true);
    console.log("按钮被点击");
  });

  root.appendChild(button);
  engine.draw(root, null);
}

图片加载

ts
function createImageLoader(engine: ITuiEngine) {
  const root = engine.createView();
  root.style.width = engine.width;
  root.style.height = engine.height;
  root.style.backgroundColor = "#ffffff";
  root.style.justifyContent = "center";
  root.style.alignItems = "center";

  // 创建图片元素
  const image = engine.createImage();
  image.style.width = 200;
  image.style.height = 200;
  image.style.backgroundColor = "#f0f0f0";
  image.style.borderRadius = 8;

  // 加载中提示
  const loadingText = engine.createText();
  loadingText.value = "加载中...";
  loadingText.style.fontSize = 14;
  loadingText.style.color = "#999999";
  loadingText.style.marginTop = 10;

  // 图片加载完成
  image.onload = (event) => {
    console.log("图片加载完成", event.detail.width, event.detail.height);
    // 移除加载提示
    if (loadingText.parentNode) {
      loadingText.parentNode.removeChild(loadingText);
    }
  };

  // 图片加载失败
  image.onerror = (event) => {
    console.error("图片加载失败", event.detail.errMsg);
    loadingText.value = "加载失败";
    engine.updateElement(loadingText, true);
  };

  // 设置图片源
  image.src = "https://example.com/image.jpg";

  root.appendChild(image, loadingText);
  engine.draw(root, null);
}

性能优化示例

局部更新

ts
function createOptimizedUpdate(engine: ITuiEngine) {
  const root = engine.createView();
  root.style.width = engine.width;
  root.style.height = engine.height;
  root.style.backgroundColor = "#ffffff";

  // 创建多个元素
  const elements: any[] = [];

  for (let i = 0; i < 10; i++) {
    const element = engine.createView();
    element.style.width = 50;
    element.style.height = 50;
    element.style.backgroundColor = "#2979ff";
    element.style.borderRadius = 8;
    element.style.position = "absolute";
    element.style.left = 10 + (i % 5) * 60;
    element.style.top = 10 + Math.floor(i / 5) * 60;

    // 添加点击事件
    element.addEventListener("click", () => {
      // 只更新点击的元素,不重绘整个画布
      element.style.backgroundColor = `#${Math.floor(Math.random() * 16777215)
        .toString(16)
        .padStart(6, "0")}`;
      engine.updateElement(element, false);
    });

    elements.push(element);
    root.appendChild(element);
  }

  engine.draw(root, null);
}

使用缓存

ts
function createCachedElements(engine: ITuiEngine) {
  const root = engine.createView();
  root.style.width = engine.width;
  root.style.height = engine.height;
  root.style.backgroundColor = "#ffffff";

  // 创建静态元素
  const staticElement = engine.createView();
  staticElement.style.width = engine.width;
  staticElement.style.height = 100;
  staticElement.style.backgroundColor = "#f0f0f0";
  staticElement.style.justifyContent = "center";
  staticElement.style.alignItems = "center";

  const staticText = engine.createText();
  staticText.value = "静态内容";
  staticText.style.fontSize = 18;
  staticText.style.color = "#333333";

  staticElement.appendChild(staticText);

  // 创建动态元素
  const dynamicElement = engine.createView();
  dynamicElement.style.width = 200;
  dynamicElement.style.height = 40;
  dynamicElement.style.backgroundColor = "#2979ff";
  dynamicElement.style.borderRadius = 20;
  dynamicElement.style.justifyContent = "center";
  dynamicElement.style.alignItems = "center";
  dynamicElement.style.marginTop = 20;

  const dynamicText = engine.createText();
  dynamicText.value = "点击更新";
  dynamicText.style.fontSize = 14;
  dynamicText.style.color = "#ffffff";

  dynamicElement.appendChild(dynamicText);

  // 添加点击事件
  dynamicElement.addEventListener("click", () => {
    dynamicText.value = `更新时间: ${new Date().toLocaleTimeString()}`;
    engine.updateElement(dynamicElement, true);
  });

  root.appendChild(staticElement, dynamicElement);

  // 绘制并缓存
  engine.draw(root, null);
  engine.cached(); // 缓存绘制结果

  console.log("元素已缓存");
}

总结

通过以上示例,你应该已经了解了 tui-entine 的基本使用方法。在实际应用中,你可以根据具体需求灵活运用这些技巧,创建各种复杂的 Canvas 交互组件。

提示:

  • 对于简单的静态布局,直接使用原生组件可能更合适
  • 对于需要高频重绘或复杂交互的场景,tui-entine 会是更好的选择
  • 合理使用局部更新和缓存,可以显著提高性能
  • 事件处理要及时清理,避免内存泄漏