使用示例
本节提供了 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会是更好的选择 - 合理使用局部更新和缓存,可以显著提高性能
- 事件处理要及时清理,避免内存泄漏