feat:数字学习卡
@@ -9,9 +9,21 @@
|
||||
"subPackages": [
|
||||
{
|
||||
"root": "mathPages",
|
||||
"pages": ["numberColor/numberColor"]
|
||||
"name": "mathPages",
|
||||
"pages": ["numberColor/numberColor"],
|
||||
"independent": false
|
||||
}
|
||||
],
|
||||
"preloadRule": {
|
||||
"pages/index/index": {
|
||||
"network": "all",
|
||||
"packages": ["mathPages"]
|
||||
},
|
||||
"pages/mathIndex/mathIndex": {
|
||||
"network": "all",
|
||||
"packages": ["mathPages"]
|
||||
}
|
||||
},
|
||||
"window": {},
|
||||
"style": "v2",
|
||||
"rendererOptions": {
|
||||
@@ -48,17 +60,17 @@
|
||||
"selectedIconPath": "assets/tabBar/icon-math-active.png",
|
||||
"text": "数学"
|
||||
},
|
||||
{
|
||||
"pagePath": "pages/copyBook/copyBook",
|
||||
"iconPath": "assets/tabBar/icon-edit.png",
|
||||
"selectedIconPath": "assets/tabBar/icon-edit-active.png",
|
||||
"text": "练字"
|
||||
},
|
||||
{
|
||||
"pagePath": "pages/shape/index",
|
||||
"iconPath": "assets/tabBar/icon-shape.png",
|
||||
"selectedIconPath": "assets/tabBar/icon-shape-active.png",
|
||||
"text": "图形"
|
||||
},
|
||||
{
|
||||
"pagePath": "pages/copyBook/copyBook",
|
||||
"iconPath": "assets/tabBar/icon-edit.png",
|
||||
"selectedIconPath": "assets/tabBar/icon-edit-active.png",
|
||||
"text": "练字"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
export interface MathFunctionType {
|
||||
id: string;
|
||||
page?: string;
|
||||
title: string;
|
||||
desc: string;
|
||||
icon: string;
|
||||
}
|
||||
|
||||
export const MATH_FUNCTION_TYPES: MathFunctionType[] = [
|
||||
{
|
||||
id: 'number-find',
|
||||
page: 'numberColor',
|
||||
title: '看数字,涂一涂',
|
||||
desc: '看数字,找一找下面相同的数字,涂上颜色',
|
||||
icon: '🔍',
|
||||
},
|
||||
{
|
||||
id: 'number-write',
|
||||
page: 'numberColor',
|
||||
title: '看数字,写一写',
|
||||
desc: '看数字,按笔画顺序写一写',
|
||||
icon: '✏️',
|
||||
},
|
||||
{
|
||||
id: 'number-coloring',
|
||||
title: '数字涂色卡',
|
||||
desc: '一边写数字、一边学数数,数字和卡通图片一一对应',
|
||||
icon: '🎨',
|
||||
},
|
||||
{
|
||||
id: 'counting-matching',
|
||||
title: '数一数,连一连',
|
||||
desc: '通过连线配对数字和对应的数量图形',
|
||||
icon: '🔗',
|
||||
},
|
||||
{
|
||||
id: 'missing-number',
|
||||
title: '填上缺少的数字',
|
||||
desc: '在数字序列中找出并填写缺失的数字',
|
||||
icon: '❓',
|
||||
},
|
||||
{
|
||||
id: 'compare',
|
||||
title: '数一数,比大小',
|
||||
desc: '通过数数比较两组物品的数量大小',
|
||||
icon: '⚖️',
|
||||
},
|
||||
{
|
||||
id: 'counting-select',
|
||||
title: '数一数,选一选',
|
||||
desc: '数出物品数量,从多个选项中选择正确答案',
|
||||
icon: '✓',
|
||||
},
|
||||
{
|
||||
id: 'counting-fill',
|
||||
title: '数一数,填一填',
|
||||
desc: '数出物品数量,填写对应的数字',
|
||||
icon: '✏️',
|
||||
},
|
||||
{
|
||||
id: 'addition-5',
|
||||
title: '5以内加法',
|
||||
desc: '练习5以内的加法运算,图形化展示',
|
||||
icon: '➕',
|
||||
},
|
||||
{
|
||||
id: 'addition-10',
|
||||
title: '10以内加法',
|
||||
desc: '练习10以内的加法运算,图形化展示',
|
||||
icon: '➕',
|
||||
},
|
||||
{
|
||||
id: 'addition-subtraction-10',
|
||||
title: '10以内加减法',
|
||||
desc: '练习10以内的加法和减法混合运算',
|
||||
icon: '±',
|
||||
},
|
||||
];
|
||||
|
Before Width: | Height: | Size: 91 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 136 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 146 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 241 KiB After Width: | Height: | Size: 53 KiB |
|
Before Width: | Height: | Size: 188 KiB After Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 326 KiB After Width: | Height: | Size: 70 KiB |
|
Before Width: | Height: | Size: 254 KiB After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 172 KiB After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 252 KiB After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 276 KiB After Width: | Height: | Size: 58 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 6.0 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 6.1 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 6.0 KiB |
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 6.0 KiB |
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 5.6 KiB |
@@ -47,22 +47,6 @@ page {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
// .canvas-wrapper {
|
||||
// width: 100%;
|
||||
// margin-bottom: 40rpx;
|
||||
// display: flex;
|
||||
// justify-content: center;
|
||||
// align-items: center;
|
||||
// background: #f8f8f8;
|
||||
// border-radius: 12rpx;
|
||||
// padding: 20rpx;
|
||||
// box-sizing: border-box;
|
||||
// }
|
||||
|
||||
// .canvas-content {
|
||||
// width: 100%;
|
||||
// height: 100%;
|
||||
// }
|
||||
}
|
||||
|
||||
/* 数字选择区域 */
|
||||
@@ -70,17 +54,18 @@ page {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20rpx;
|
||||
margin-top: 40rpx;
|
||||
}
|
||||
|
||||
.number-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 60rpx;
|
||||
gap: 40rpx;
|
||||
width: 100%;
|
||||
margin-top: 40rpx;
|
||||
}
|
||||
|
||||
.number-item {
|
||||
height: 90rpx;
|
||||
background: #ffffff;
|
||||
border: 2rpx solid #e8e8e8;
|
||||
border-radius: 16rpx;
|
||||
@@ -90,26 +75,43 @@ page {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex: 1;
|
||||
box-sizing: border-box;
|
||||
min-width: 0;
|
||||
position: relative;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08), 0 2rpx 4rpx rgba(0, 0, 0, 0.06);
|
||||
|
||||
&:active {
|
||||
transform: scale(0.98);
|
||||
box-shadow: 0 2rpx 6rpx rgba(0, 0, 0, 0.1), 0 1rpx 2rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
&.active {
|
||||
border-color: #93d333;
|
||||
box-shadow: 0 0 0 4rpx rgba(147, 211, 51, 0.2);
|
||||
box-shadow: 0 4rpx 16rpx rgba(147, 211, 51, 0.25), 0 0 0 4rpx rgba(147, 211, 51, 0.15);
|
||||
}
|
||||
|
||||
.number-text {
|
||||
font-size: 28rpx;
|
||||
color: #141414;
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
color: #141414;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.number-column {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 40rpx;
|
||||
|
||||
.number-item {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.random-button {
|
||||
flex: 2;
|
||||
}
|
||||
|
||||
/* 随机按钮样式 */
|
||||
&.random-button {
|
||||
@@ -134,7 +136,7 @@ page {
|
||||
}
|
||||
|
||||
.number-text {
|
||||
// flex: 0;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
&.active {
|
||||
@@ -154,13 +156,12 @@ page {
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 200rpx;
|
||||
height: 180rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
background-color: #fff;
|
||||
box-shadow: 0px -3.9rpx 5.2rpx rgba(0, 0, 0, 0.15);
|
||||
padding: 0 24rpx;
|
||||
padding: 24rpx;
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
box-sizing: border-box;
|
||||
border-radius: 16rpx 16rpx 0 0;
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
import { PAPER_SIZE } from '../../constants/colors';
|
||||
import { checkAndSaveImage } from '../../utils/saveImage';
|
||||
import { shouldShowShareGuide } from '../../utils/shareGuide';
|
||||
import NumberColorDraw from '../service/numberColorDraw';
|
||||
import {
|
||||
MATH_FUNCTION_TYPES,
|
||||
MathFunctionType,
|
||||
} from '../../constants/mathFunctions';
|
||||
|
||||
Page({
|
||||
canvas: null as Canvas | null,
|
||||
ctx: null as RenderingContext | null,
|
||||
boxHeight: 0,
|
||||
boxWidth: 0,
|
||||
drawService: null as NumberColorDraw | null,
|
||||
|
||||
data: {
|
||||
pageTitle: '看数字,涂一涂', // 默认标题
|
||||
@@ -18,26 +24,17 @@ Page({
|
||||
|
||||
onLoad(options: { id?: string }) {
|
||||
// 根据id参数判断页面标题
|
||||
const functionId = options.id || 'number-find-color';
|
||||
const functionId = options.id || 'number-find';
|
||||
this.setData({
|
||||
functionId,
|
||||
});
|
||||
|
||||
// 根据functionId设置页面标题
|
||||
const titleMap: Record<string, string> = {
|
||||
'number-find-color': '看数字,涂一涂',
|
||||
'number-coloring': '数字涂色卡',
|
||||
'counting-matching': '数一数,连一连',
|
||||
'missing-number': '填上缺少的数字',
|
||||
compare: '数一数,比大小',
|
||||
'counting-select': '数一数,选一选',
|
||||
'counting-fill': '数一数,填一填',
|
||||
'addition-5': '5以内加法',
|
||||
'addition-10': '10以内加法',
|
||||
'addition-subtraction-10': '10以内加减法',
|
||||
};
|
||||
const functionItem = MATH_FUNCTION_TYPES.find(
|
||||
(item: MathFunctionType) => item.id === functionId,
|
||||
);
|
||||
|
||||
const pageTitle = titleMap[functionId] || '看数字,涂一涂';
|
||||
const pageTitle = functionItem?.title || '看数字,涂一涂';
|
||||
this.setData({
|
||||
pageTitle,
|
||||
});
|
||||
@@ -91,6 +88,26 @@ Page({
|
||||
this.canvas = canvasNode;
|
||||
this.ctx = ctx;
|
||||
|
||||
// 初始化绘制服务
|
||||
this.drawService = new NumberColorDraw(
|
||||
canvasNode,
|
||||
ctx,
|
||||
{
|
||||
title: this.data.pageTitle,
|
||||
subTitle: '找一找下面相同的数字,涂上颜色',
|
||||
functionId: this.data.functionId,
|
||||
},
|
||||
);
|
||||
|
||||
// 如果还没有选中数字,随机选择一个
|
||||
if (this.data.selectedNumber === 0) {
|
||||
const randomNumber =
|
||||
Math.floor(Math.random() * 10) + 1;
|
||||
this.setData({
|
||||
selectedNumber: randomNumber,
|
||||
});
|
||||
}
|
||||
|
||||
// 绘制初始内容
|
||||
this.drawCanvas();
|
||||
}
|
||||
@@ -103,34 +120,17 @@ Page({
|
||||
/**
|
||||
* 绘制Canvas内容
|
||||
*/
|
||||
drawCanvas() {
|
||||
if (!this.ctx) {
|
||||
async drawCanvas() {
|
||||
if (!this.ctx || !this.drawService) {
|
||||
return;
|
||||
}
|
||||
|
||||
const ctx = this.ctx;
|
||||
const width = this.boxWidth;
|
||||
const height = this.boxHeight;
|
||||
|
||||
// 清空画布
|
||||
ctx.clearRect(0, 0, width, height);
|
||||
|
||||
// 设置背景色
|
||||
ctx.fillStyle = '#FFFFFF';
|
||||
ctx.fillRect(0, 0, width, height);
|
||||
|
||||
// TODO: 根据选中的数字绘制内容
|
||||
if (this.data.selectedNumber > 0) {
|
||||
// 绘制示例:显示选中的数字
|
||||
ctx.fillStyle = '#141414';
|
||||
ctx.font = 'bold 120px sans-serif';
|
||||
ctx.textAlign = 'center';
|
||||
ctx.textBaseline = 'middle';
|
||||
ctx.fillText(
|
||||
String(this.data.selectedNumber),
|
||||
width / 2,
|
||||
height / 2,
|
||||
);
|
||||
try {
|
||||
await this.drawService.draw(this.data.selectedNumber);
|
||||
} catch (error) {
|
||||
console.error('绘制失败:', error);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
|
||||
<!-- 第三行:9、10和随机按钮 -->
|
||||
<view class="number-row">
|
||||
<view class="number-column">
|
||||
<view
|
||||
wx:for="{{numberList}}"
|
||||
wx:key="index"
|
||||
@@ -53,11 +54,17 @@
|
||||
bind:tap="onSelectNumber">
|
||||
<view class="number-text">{{number}}</view>
|
||||
</view>
|
||||
<view class="number-item random-button" bind:tap="onRandom">
|
||||
<view class="random-icon">
|
||||
<text class="toy-icon toy-icon-refresh"></text>
|
||||
</view>
|
||||
<view class="number-text">随机</view>
|
||||
<view class="number-column">
|
||||
<toy-button
|
||||
style="width: 100%"
|
||||
type="primary"
|
||||
bind:click="onRandom"
|
||||
width="100%"
|
||||
icon="refresh"
|
||||
icon-class-prefix="toy-icon">
|
||||
随机
|
||||
</toy-button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
import { PAPER_SIZE } from '../../constants/colors';
|
||||
import { drawMathHeader, drawMathMiniHeader } from './mathHeaderDraw';
|
||||
|
||||
/**
|
||||
* 基础数学绘制服务
|
||||
* 包含Paper设置和Header绘制功能,可被其他绘制服务复用
|
||||
*/
|
||||
export class BaseMathDrawService {
|
||||
headerType: PrintHeader = 'wechat';
|
||||
canvas: WechatMiniprogram.Canvas;
|
||||
ctx: RenderingContext;
|
||||
options: Record<string, any>;
|
||||
paperSize: PaperSize;
|
||||
currentX: number;
|
||||
currentY: number;
|
||||
canvasWidth: number; // 逻辑像素宽度
|
||||
canvasHeight: number; // 逻辑像素高度
|
||||
|
||||
constructor(
|
||||
canvas: Canvas,
|
||||
ctx: RenderingContext,
|
||||
options?: Record<string, any>,
|
||||
) {
|
||||
options = options || {};
|
||||
this.canvas = canvas;
|
||||
this.ctx = ctx;
|
||||
this.paperSize = 'A4';
|
||||
this.options = {
|
||||
appName: '涂鸦丫小程序',
|
||||
appHint: '在玩耍中学习数学',
|
||||
title: '看数字,涂一涂',
|
||||
subTitle: '找一找下面相同的数字,涂上颜色',
|
||||
...options,
|
||||
};
|
||||
this.currentX = 0;
|
||||
this.currentY = 0;
|
||||
this.canvasWidth = 0;
|
||||
this.canvasHeight = 0;
|
||||
this.setPrintConfig();
|
||||
}
|
||||
|
||||
setPrintConfig() {
|
||||
const printConfig = getApp().getPrintConfig();
|
||||
this.headerType = printConfig.header;
|
||||
this.options.appName = printConfig.appName;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置Paper(逻辑像素,尺寸除以3)
|
||||
*/
|
||||
setPaper() {
|
||||
const { ctx, canvas } = this;
|
||||
const { pixelRatio: dpr } = wx.getWindowInfo();
|
||||
let { width, height } = PAPER_SIZE[this.paperSize];
|
||||
console.log('width', width);
|
||||
console.log('height', height);
|
||||
console.log('dpr', dpr);
|
||||
|
||||
this.canvasWidth = width;
|
||||
this.canvasHeight = height;
|
||||
|
||||
// 设置 canvas 为物理像素尺寸(用于高分辨率显示)
|
||||
const physicalWidth = width * dpr;
|
||||
const physicalHeight = height * dpr;
|
||||
canvas.width = physicalWidth;
|
||||
canvas.height = physicalHeight;
|
||||
|
||||
// 重置 transform 并 scale 到逻辑像素
|
||||
ctx.setTransform(1, 0, 0, 1, 0, 0); // 重置 transform
|
||||
ctx.scale(dpr, dpr); // scale 到逻辑像素,后续绘制都使用逻辑像素
|
||||
|
||||
this.clear();
|
||||
ctx.fillStyle = '#fff';
|
||||
// 使用逻辑像素尺寸填充
|
||||
ctx.fillRect(0, 0, this.canvasWidth, this.canvasHeight);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除画布
|
||||
*/
|
||||
clear() {
|
||||
const canvas = this.canvas;
|
||||
this.ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
}
|
||||
|
||||
/**
|
||||
* 绘制Header(逻辑像素,尺寸除以3)
|
||||
*/
|
||||
async drawHeader() {
|
||||
this.currentX = 24;
|
||||
this.currentY = 24;
|
||||
await drawMathHeader({
|
||||
canvas: this.canvas,
|
||||
ctx: this.ctx,
|
||||
headerType: this.headerType,
|
||||
options: {
|
||||
appName: this.options.appName || '涂鸦丫小程序',
|
||||
appHint: this.options.appHint || '识字|识图|练字|打印',
|
||||
title: this.options.title || '看数字,涂一涂',
|
||||
subTitle:
|
||||
this.options.subTitle || '找一找下面相同的数字,涂上颜色',
|
||||
},
|
||||
onHeaderDrawn: (currentY) => {
|
||||
this.currentY = currentY;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 绘制迷你Header(逻辑像素,尺寸除以3)
|
||||
*/
|
||||
drawMiniHeader() {
|
||||
drawMathMiniHeader({
|
||||
ctx: this.ctx,
|
||||
canvasWidth: this.canvasWidth,
|
||||
options: {
|
||||
appName: this.options.appName || '涂鸦丫小程序',
|
||||
title: this.options.title || '看数字,涂一涂',
|
||||
},
|
||||
onHeaderDrawn: (currentY) => {
|
||||
this.currentY = currentY;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 绘制分割线(逻辑像素,尺寸除以3)
|
||||
*/
|
||||
drawDivider() {
|
||||
const { ctx, canvasWidth } = this;
|
||||
const dividerY = this.currentY + 10; // 10px间距
|
||||
|
||||
ctx.strokeStyle = '#000';
|
||||
ctx.lineWidth = 1;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(24, dividerY);
|
||||
ctx.lineTo(canvasWidth - 24, dividerY);
|
||||
ctx.stroke();
|
||||
|
||||
this.currentY = dividerY + 10; // 分割线下方10px间距
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
import { getMiniCodeImage, getImage } from '../../utils/index';
|
||||
|
||||
/**
|
||||
* 绘制数学模块页眉的参数接口(尺寸除以3)
|
||||
*/
|
||||
interface DrawMathHeaderParams {
|
||||
canvas: WechatMiniprogram.Canvas;
|
||||
ctx: RenderingContext;
|
||||
headerType: PrintHeader;
|
||||
options: {
|
||||
appName: string;
|
||||
appHint: string;
|
||||
title: string;
|
||||
subTitle: string;
|
||||
};
|
||||
onHeaderDrawn?: (currentY: number) => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* 绘制数学模块完整页眉(尺寸除以3)
|
||||
*/
|
||||
export async function drawMathHeader({
|
||||
canvas,
|
||||
ctx,
|
||||
headerType,
|
||||
options,
|
||||
onHeaderDrawn,
|
||||
}: DrawMathHeaderParams): Promise<void> {
|
||||
const { appName, appHint, title, subTitle } = options;
|
||||
|
||||
let titleX = 108; // 约109.33
|
||||
const titleY = 26; // 约26.67
|
||||
|
||||
const logoX = 24; // 约26.67
|
||||
const logoY = 20; // 20
|
||||
const logoWidth = 65; // 约66.67
|
||||
const logoHeight = 65; // 约66.67
|
||||
|
||||
// 根据 headerType 绘制 Logo 或调整标题位置
|
||||
switch (headerType) {
|
||||
case 'LogoImage': {
|
||||
const image = await getImage(
|
||||
canvas,
|
||||
'/assets/imgs/doodle-logo.png',
|
||||
);
|
||||
ctx.drawImage(image, logoX, logoY, logoWidth, logoHeight);
|
||||
break;
|
||||
}
|
||||
case 'noLogoImage': {
|
||||
titleX = 40;
|
||||
break;
|
||||
}
|
||||
case 'minimal': {
|
||||
titleX = 40;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
const image = await getMiniCodeImage(canvas);
|
||||
ctx.drawImage(image, logoX, logoY, logoWidth, logoHeight);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 绘制应用名称(字体大小除以3)
|
||||
ctx.font = 'bold 22px "Microsoft Yahei"';
|
||||
ctx.fillStyle = '#000';
|
||||
ctx.textAlign = 'left';
|
||||
ctx.textBaseline = 'top';
|
||||
ctx.fillText(appName, titleX, titleY);
|
||||
|
||||
// 绘制应用提示(字体大小除以3)
|
||||
ctx.font = '16px "Microsoft Yahei"';
|
||||
ctx.fillStyle = '#666';
|
||||
ctx.fillText(appHint, titleX, 66);
|
||||
|
||||
// 绘制标题(字体大小除以3)
|
||||
ctx.font = 'bold 22px "Microsoft Yahei"';
|
||||
ctx.fillStyle = '#000';
|
||||
ctx.fillText(title, 280, titleY);
|
||||
|
||||
// 绘制副标题(字体大小除以3)
|
||||
ctx.font = '16px "Microsoft Yahei"';
|
||||
ctx.fillStyle = '#666';
|
||||
ctx.fillText(subTitle, 280, 66);
|
||||
|
||||
// 调用回调函数
|
||||
if (onHeaderDrawn) {
|
||||
onHeaderDrawn(100);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 绘制数学模块迷你页眉的参数接口(尺寸除以3)
|
||||
*/
|
||||
interface DrawMathMiniHeaderParams {
|
||||
// canvas: WechatMiniprogram.Canvas;
|
||||
ctx: RenderingContext;
|
||||
options: {
|
||||
appName: string;
|
||||
title: string;
|
||||
};
|
||||
canvasWidth: number; // 逻辑像素宽度(已除以3)
|
||||
onHeaderDrawn?: (currentY: number) => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* 绘制数学模块迷你页眉(尺寸除以3)
|
||||
*/
|
||||
export function drawMathMiniHeader({
|
||||
ctx,
|
||||
options,
|
||||
canvasWidth,
|
||||
onHeaderDrawn,
|
||||
}: DrawMathMiniHeaderParams): void {
|
||||
const { appName, title } = options;
|
||||
const titleY = 46;
|
||||
const centerX = canvasWidth / 2;
|
||||
|
||||
// 字体大小除以3
|
||||
ctx.font = 'bold 24px "Microsoft Yahei"'; // 64/3
|
||||
ctx.fillStyle = '#000';
|
||||
ctx.textAlign = 'center';
|
||||
ctx.fillText(appName + ' ' + title, centerX, titleY);
|
||||
|
||||
// 调用回调函数,传递除以3后的currentY
|
||||
if (onHeaderDrawn) {
|
||||
onHeaderDrawn(64); // 约66.67
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
import { BaseMathDrawService } from './baseMathDraw';
|
||||
import { drawNumberPreview } from './numberPreviewDraw';
|
||||
import { drawNumberContent } from './numberContentDraw';
|
||||
import { drawNumberWriteContent } from './numberWriteDraw';
|
||||
|
||||
/**
|
||||
* 数字涂色绘制服务
|
||||
* 组合使用基础绘制服务、预览区域绘制服务和内容区域绘制服务
|
||||
*/
|
||||
class NumberColorDraw extends BaseMathDrawService {
|
||||
selectedNumber: number;
|
||||
functionId: string; // 功能ID,用于判断绘制类型
|
||||
|
||||
constructor(
|
||||
canvas: Canvas,
|
||||
ctx: RenderingContext,
|
||||
options?: Record<string, any>,
|
||||
) {
|
||||
super(canvas, ctx, options);
|
||||
this.selectedNumber = 0;
|
||||
this.functionId = options?.functionId || 'number-find';
|
||||
}
|
||||
|
||||
async draw(selectedNumber: number) {
|
||||
if (selectedNumber <= 0 || selectedNumber > 10) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.setPrintConfig();
|
||||
this.selectedNumber = selectedNumber;
|
||||
this.clear();
|
||||
this.setPaper();
|
||||
|
||||
// 绘制Header
|
||||
if (this.headerType !== 'minimal') {
|
||||
await this.drawHeader();
|
||||
} else {
|
||||
this.drawMiniHeader();
|
||||
}
|
||||
|
||||
// 绘制预览区域
|
||||
this.drawDivider();
|
||||
await drawNumberPreview({
|
||||
canvas: this.canvas,
|
||||
ctx: this.ctx,
|
||||
selectedNumber: this.selectedNumber,
|
||||
canvasWidth: this.canvasWidth,
|
||||
startY: this.currentY,
|
||||
onDrawn: (currentY) => {
|
||||
this.currentY = currentY;
|
||||
},
|
||||
});
|
||||
|
||||
// 绘制内容区域(根据 functionId 选择不同的绘制方法)
|
||||
this.drawDivider();
|
||||
if (this.functionId === 'number-write') {
|
||||
// 书写类型:绘制书写行
|
||||
drawNumberWriteContent({
|
||||
ctx: this.ctx,
|
||||
selectedNumber: this.selectedNumber,
|
||||
canvasWidth: this.canvasWidth,
|
||||
startY: this.currentY,
|
||||
});
|
||||
} else {
|
||||
// 默认类型(number-find):绘制数字涂色内容
|
||||
drawNumberContent({
|
||||
ctx: this.ctx,
|
||||
selectedNumber: this.selectedNumber,
|
||||
canvasWidth: this.canvasWidth,
|
||||
startY: this.currentY,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default NumberColorDraw;
|
||||
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* 绘制内容区域的参数接口
|
||||
*/
|
||||
interface DrawNumberContentParams {
|
||||
ctx: RenderingContext;
|
||||
selectedNumber: number;
|
||||
canvasWidth: number; // 逻辑像素宽度(已除以3)
|
||||
startY: number; // 起始Y坐标
|
||||
}
|
||||
|
||||
/**
|
||||
* 绘制数字涂色内容区域服务
|
||||
* 随机绘制1-10的数字,尺寸除以3
|
||||
*/
|
||||
export function drawNumberContent({
|
||||
ctx,
|
||||
selectedNumber,
|
||||
canvasWidth,
|
||||
startY,
|
||||
}: DrawNumberContentParams): void {
|
||||
const rows = 6;
|
||||
const radius = 26; // 约26.67
|
||||
const fontSize = 24; // 24
|
||||
|
||||
const startYPos = startY + 10 + radius; // 约47.33
|
||||
const startX1 = 100 + radius; // 约112.22
|
||||
const startX2 = 60 + radius; // 约75.56
|
||||
const spaceWidthFirst = (canvasWidth - startX1 * 2) / (5 - 1);
|
||||
const spaceWidthSecond = (canvasWidth - startX2 * 2) / (6 - 1);
|
||||
const spaceHeight = 18; // 18
|
||||
|
||||
ctx.moveTo(startX1, startYPos);
|
||||
for (let i = 0; i < rows; i++) {
|
||||
const cols = i % 2 === 0 ? 5 : 6;
|
||||
|
||||
for (let j = 0; j < cols; j++) {
|
||||
const y = startYPos + i * (spaceHeight + radius * 2);
|
||||
const x =
|
||||
i % 2 === 0
|
||||
? startX1 + j * spaceWidthFirst
|
||||
: startX2 + j * spaceWidthSecond;
|
||||
|
||||
// 随机生成1-10的数字,但确保包含选中的数字
|
||||
let number: number;
|
||||
if (i === 0 && j === 0) {
|
||||
// 第一个位置固定为选中的数字
|
||||
number = selectedNumber;
|
||||
} else {
|
||||
// 其他位置随机,但增加选中数字出现的概率
|
||||
const random = Math.random();
|
||||
if (random < 0.3) {
|
||||
// 30%概率是选中的数字
|
||||
number = selectedNumber;
|
||||
} else {
|
||||
// 70%概率是其他随机数字
|
||||
number = Math.floor(Math.random() * 10) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// 绘制圆形背景(线宽除以3)
|
||||
ctx.fillStyle = '#fff';
|
||||
ctx.strokeStyle = '#000';
|
||||
ctx.lineWidth = 1; // 约1.33
|
||||
ctx.beginPath();
|
||||
ctx.arc(x, y, radius, 0, Math.PI * 2);
|
||||
ctx.fill();
|
||||
ctx.stroke();
|
||||
ctx.closePath();
|
||||
|
||||
// 绘制数字(字体大小除以3)
|
||||
ctx.fillStyle = '#333';
|
||||
ctx.font = `bold ${fontSize}px "Microsoft Yahei"`;
|
||||
ctx.textBaseline = 'middle';
|
||||
ctx.textAlign = 'center';
|
||||
ctx.fillText(String(number), x, y, radius * 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
import { getImage } from '../../utils/index';
|
||||
|
||||
/**
|
||||
* 数字到英文单词的映射
|
||||
*/
|
||||
const NUMBER_WORDS: Record<number, string> = {
|
||||
1: 'one',
|
||||
2: 'two',
|
||||
3: 'three',
|
||||
4: 'four',
|
||||
5: 'five',
|
||||
6: 'six',
|
||||
7: 'seven',
|
||||
8: 'eight',
|
||||
9: 'nine',
|
||||
10: 'ten',
|
||||
};
|
||||
|
||||
const NUMBER_COLORS: Record<number, string> = {
|
||||
1: '#9FC558',
|
||||
2: '#CDB984',
|
||||
3: '#B393B8',
|
||||
4: '#ED7E97',
|
||||
5: '#53B5B9',
|
||||
6: '#B3B3B3',
|
||||
7: '#EE8B7A',
|
||||
8: '#F6C644',
|
||||
9: '#99C1F4',
|
||||
10: '#F5D25C',
|
||||
};
|
||||
|
||||
/**
|
||||
* 绘制预览区域的参数接口
|
||||
*/
|
||||
interface DrawNumberPreviewParams {
|
||||
canvas: WechatMiniprogram.Canvas;
|
||||
ctx: RenderingContext;
|
||||
selectedNumber: number;
|
||||
canvasWidth: number; // 逻辑像素宽度(已除以3)
|
||||
startY: number; // 起始Y坐标
|
||||
onDrawn?: (currentY: number) => void; // 绘制完成后的回调
|
||||
}
|
||||
|
||||
/**
|
||||
* 绘制数字预览区域服务
|
||||
* 左侧:animal-number 图片
|
||||
* 右侧:两个框,第一个框是finger图片,第二个框是英文单词
|
||||
* 所有尺寸除以3
|
||||
*/
|
||||
export async function drawNumberPreview({
|
||||
canvas,
|
||||
ctx,
|
||||
selectedNumber,
|
||||
canvasWidth,
|
||||
startY,
|
||||
onDrawn,
|
||||
}: DrawNumberPreviewParams): Promise<void> {
|
||||
// 左侧 animal-number 图片位置
|
||||
const animalImageWidth = 360;
|
||||
const animalImageHeight = 236;
|
||||
const leftMargin = 35;
|
||||
const animalImageX = leftMargin;
|
||||
const animalImageY = startY + 10;
|
||||
|
||||
// 加载并绘制 animal-number 图片
|
||||
try {
|
||||
const animalImagePath = `/mathPages/assets/animal-number/animal-number-${selectedNumber}.png`;
|
||||
const animalImage = await getImage(canvas, animalImagePath);
|
||||
ctx.drawImage(
|
||||
animalImage,
|
||||
animalImageX,
|
||||
animalImageY,
|
||||
animalImageWidth,
|
||||
animalImageHeight,
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('加载animal-number图片失败:', error);
|
||||
}
|
||||
|
||||
// 右侧两个框的位置(逻辑像素,除以3)
|
||||
const boxWidth = 130;
|
||||
const boxHeight = 100;
|
||||
const rightMargin = 35;
|
||||
const boxSpacing = 30;
|
||||
const boxX = canvasWidth - rightMargin - boxWidth;
|
||||
|
||||
// 第一个框:finger 图片
|
||||
const fingerBoxY = animalImageY;
|
||||
ctx.strokeStyle = '#000';
|
||||
ctx.lineWidth = 1;
|
||||
ctx.strokeRect(boxX, fingerBoxY, boxWidth, boxHeight);
|
||||
|
||||
try {
|
||||
const fingerImagePath = `/mathPages/assets/finger/finger-${selectedNumber}.png`;
|
||||
const fingerImage = await getImage(canvas, fingerImagePath);
|
||||
// 计算图片在框内的位置(居中显示)
|
||||
const imagePadding = 10;
|
||||
const imageWidth = boxWidth - imagePadding * 2;
|
||||
const imageHeight = boxHeight - imagePadding * 2;
|
||||
ctx.drawImage(
|
||||
fingerImage,
|
||||
boxX + imagePadding,
|
||||
fingerBoxY + imagePadding,
|
||||
imageWidth,
|
||||
imageHeight,
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('加载finger图片失败:', error);
|
||||
}
|
||||
|
||||
// 第二个框:英文单词
|
||||
const wordBoxY = fingerBoxY + boxHeight + boxSpacing;
|
||||
ctx.strokeRect(boxX, wordBoxY, boxWidth, boxHeight);
|
||||
|
||||
// 绘制英文单词(字体大小除以3)
|
||||
const word = NUMBER_WORDS[selectedNumber] || '';
|
||||
const color = NUMBER_COLORS[selectedNumber] || '#000';
|
||||
ctx.fillStyle = color;
|
||||
// 推荐使用系统内常见的圆体或幼圆体字体,更适合儿童视觉风格
|
||||
ctx.font =
|
||||
'bold 32px "HarmonyOS Sans", "PingFang SC", "YouYuan", "Microsoft Yahei", sans-serif';
|
||||
ctx.textAlign = 'center';
|
||||
ctx.textBaseline = 'middle';
|
||||
ctx.fillText(
|
||||
word,
|
||||
boxX + boxWidth / 2,
|
||||
wordBoxY + boxHeight / 2,
|
||||
boxWidth - 20,
|
||||
);
|
||||
|
||||
// 更新 currentY 为预览区域底部
|
||||
const finalY =
|
||||
Math.max(animalImageY + animalImageHeight, wordBoxY + boxHeight) + 10;
|
||||
|
||||
if (onDrawn) {
|
||||
onDrawn(finalY);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/**
|
||||
* 绘制书写行内容区域的参数接口
|
||||
*/
|
||||
interface DrawNumberWriteContentParams {
|
||||
ctx: RenderingContext;
|
||||
selectedNumber: number;
|
||||
canvasWidth: number; // 逻辑像素宽度
|
||||
startY: number; // 起始Y坐标
|
||||
}
|
||||
|
||||
/**
|
||||
* 绘制数字书写内容区域服务
|
||||
* 绘制三条书写行,每条行有三条线(上下实线,中间虚线)
|
||||
* 第一行和第二行有数字(第一个黑色实线,后续灰色虚线),第三行空白
|
||||
*/
|
||||
export function drawNumberWriteContent({
|
||||
ctx,
|
||||
selectedNumber,
|
||||
canvasWidth,
|
||||
startY,
|
||||
}: DrawNumberWriteContentParams): void {
|
||||
const lineSpacing = 30; // 行间距(三条线之间的间距)
|
||||
const rowHeight = lineSpacing * 2; // 每行的高度(两条实线之间的距离)
|
||||
const rowMargin = 24; // 行与行之间的间距
|
||||
const leftMargin = 24; // 左边距
|
||||
const rightMargin = 24; // 右边距
|
||||
const numberIndent = selectedNumber === 10 ? 12 : 24; // 数字缩进(避免贴边)
|
||||
const numberSpacing = 90; // 数字之间的间距
|
||||
const numberCount = 6; // 每行数字的数量(第一个实线 + 6个虚线)
|
||||
const fontSize = 76; // 数字字体大小(调整为行高的83%,避免超出上下边线)
|
||||
|
||||
// 计算每行的起始Y坐标
|
||||
const rowStartY = startY + 20; // 顶部间距
|
||||
|
||||
// 绘制三条书写行
|
||||
for (let rowIndex = 0; rowIndex < 5; rowIndex++) {
|
||||
const rowY = rowStartY + rowIndex * (rowHeight + rowMargin);
|
||||
const topLineY = rowY;
|
||||
const middleLineY = rowY + lineSpacing;
|
||||
const bottomLineY = rowY + rowHeight;
|
||||
|
||||
// 绘制上实线(蓝色)
|
||||
ctx.strokeStyle = '#4A90E2'; // 蓝色
|
||||
ctx.lineWidth = 1;
|
||||
ctx.setLineDash([]); // 实线
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(leftMargin, topLineY);
|
||||
ctx.lineTo(canvasWidth - rightMargin, topLineY);
|
||||
ctx.stroke();
|
||||
|
||||
// 绘制中间虚线(橙色)
|
||||
ctx.strokeStyle = '#FF8C42'; // 橙色
|
||||
ctx.lineWidth = 1;
|
||||
ctx.setLineDash([12, 12]); // 虚线模式
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(leftMargin, middleLineY);
|
||||
ctx.lineTo(canvasWidth - rightMargin, middleLineY);
|
||||
ctx.stroke();
|
||||
ctx.setLineDash([]); // 恢复实线模式
|
||||
|
||||
// 绘制下实线(蓝色)
|
||||
ctx.strokeStyle = '#4A90E2'; // 蓝色
|
||||
ctx.lineWidth = 1;
|
||||
ctx.setLineDash([]); // 实线
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(leftMargin, bottomLineY);
|
||||
ctx.lineTo(canvasWidth - rightMargin, bottomLineY);
|
||||
ctx.stroke();
|
||||
|
||||
// 第一行和第二行绘制数字
|
||||
if (rowIndex < 3) {
|
||||
const centerY = rowY + lineSpacing; // 数字中心Y坐标(中间虚线位置)
|
||||
|
||||
for (let i = 0; i < numberCount; i++) {
|
||||
const numberX = leftMargin + numberIndent + i * numberSpacing;
|
||||
|
||||
if (i === 0) {
|
||||
// 第一个数字:黑色实线
|
||||
ctx.fillStyle = '#000000';
|
||||
ctx.font = `bold ${fontSize}px "Microsoft Yahei"`;
|
||||
ctx.textBaseline = 'middle';
|
||||
ctx.textAlign = 'left';
|
||||
ctx.fillText(String(selectedNumber), numberX, centerY);
|
||||
} else {
|
||||
// 后续数字:灰色虚线(使用灰色填充配合透明度模拟虚线效果)
|
||||
const savedAlpha = ctx.globalAlpha;
|
||||
ctx.globalAlpha = 0.6; // 设置透明度模拟虚线效果
|
||||
ctx.fillStyle = '#999999'; // 灰色
|
||||
ctx.font = `${fontSize}px "Microsoft Yahei"`;
|
||||
ctx.textBaseline = 'middle';
|
||||
ctx.textAlign = 'left';
|
||||
ctx.fillText(String(selectedNumber), numberX, centerY);
|
||||
ctx.globalAlpha = savedAlpha; // 恢复透明度
|
||||
}
|
||||
}
|
||||
}
|
||||
// 第三行不绘制数字(空白行)
|
||||
}
|
||||
}
|
||||
@@ -161,5 +161,12 @@ page {
|
||||
font-size: 24rpx;
|
||||
color: #666666;
|
||||
line-height: 1.5;
|
||||
white-space: pre-line;
|
||||
|
||||
view {
|
||||
margin-bottom: 8rpx;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,68 +1,8 @@
|
||||
import { MATH_FUNCTION_TYPES } from '../../constants/mathFunctions';
|
||||
|
||||
Page({
|
||||
data: {
|
||||
functionList: [
|
||||
{
|
||||
id: 'number-find-color',
|
||||
page: 'numberColor',
|
||||
title: '看数字,涂一涂',
|
||||
desc: '给一个数字,找一找下面相同的数字,涂上颜色',
|
||||
icon: '🔍',
|
||||
},
|
||||
{
|
||||
id: 'number-coloring',
|
||||
title: '数字涂色卡',
|
||||
desc: '一边写数字、一边学数数,数字和卡通图片一一对应',
|
||||
icon: '🎨',
|
||||
},
|
||||
{
|
||||
id: 'counting-matching',
|
||||
title: '数一数,连一连',
|
||||
desc: '通过连线配对数字和对应的数量图形',
|
||||
icon: '🔗',
|
||||
},
|
||||
{
|
||||
id: 'missing-number',
|
||||
title: '填上缺少的数字',
|
||||
desc: '在数字序列中找出并填写缺失的数字',
|
||||
icon: '❓',
|
||||
},
|
||||
{
|
||||
id: 'compare',
|
||||
title: '数一数,比大小',
|
||||
desc: '通过数数比较两组物品的数量大小',
|
||||
icon: '⚖️',
|
||||
},
|
||||
{
|
||||
id: 'counting-select',
|
||||
title: '数一数,选一选',
|
||||
desc: '数出物品数量,从多个选项中选择正确答案',
|
||||
icon: '✓',
|
||||
},
|
||||
{
|
||||
id: 'counting-fill',
|
||||
title: '数一数,填一填',
|
||||
desc: '数出物品数量,填写对应的数字',
|
||||
icon: '✏️',
|
||||
},
|
||||
{
|
||||
id: 'addition-5',
|
||||
title: '5以内加法',
|
||||
desc: '练习5以内的加法运算,图形化展示',
|
||||
icon: '➕',
|
||||
},
|
||||
{
|
||||
id: 'addition-10',
|
||||
title: '10以内加法',
|
||||
desc: '练习10以内的加法运算,图形化展示',
|
||||
icon: '➕',
|
||||
},
|
||||
{
|
||||
id: 'addition-subtraction-10',
|
||||
title: '10以内加减法',
|
||||
desc: '练习10以内的加法和减法混合运算',
|
||||
icon: '±',
|
||||
},
|
||||
],
|
||||
functionList: MATH_FUNCTION_TYPES,
|
||||
},
|
||||
|
||||
onLoad() {
|
||||
@@ -89,9 +29,9 @@ Page({
|
||||
});
|
||||
} else {
|
||||
wx.showToast({
|
||||
title: `即将打开:${functionItem.title}`,
|
||||
title: `功能开发中,敬请期待`,
|
||||
icon: 'none',
|
||||
duration: 2000,
|
||||
duration: 2500,
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
@@ -32,9 +32,10 @@
|
||||
<view class="hint-text">
|
||||
<view class="hint-title">使用提示</view>
|
||||
<view class="hint-desc">
|
||||
1. 点击上方功能卡片选择要生成的涂鸦卡类型\n 2.
|
||||
选择数字范围、图形类型等参数\n 3. 预览生成的涂鸦卡效果\n 4.
|
||||
下载A4格式PNG图片,打印后使用
|
||||
<view>1. 点击上方功能卡片选择要生成的涂鸦卡类型</view>
|
||||
<view>2. 选择数字等参数</view>
|
||||
<view>3. 预览生成的涂鸦卡效果</view>
|
||||
<view>4. 下载A4格式PNG图片,打印后使用</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -99,6 +99,7 @@ interface DrawMiniHeaderParams {
|
||||
appName: string;
|
||||
title: string;
|
||||
};
|
||||
canvasWidth?: number; // 逻辑像素宽度(可选,如果提供则使用,否则从 canvas.width 计算)
|
||||
onHeaderDrawn?: (currentY: number) => void; // 绘制完成后的回调,用于设置 currentY 和绘制分割线
|
||||
}
|
||||
|
||||
@@ -109,15 +110,20 @@ export function drawMiniHeader({
|
||||
canvas,
|
||||
ctx,
|
||||
options,
|
||||
canvasWidth,
|
||||
onHeaderDrawn,
|
||||
}: DrawMiniHeaderParams): void {
|
||||
const { appName, title } = options;
|
||||
const titleY = 120;
|
||||
|
||||
// 如果提供了逻辑宽度,使用它;否则使用 canvas.width(假设 ctx 未 scale)
|
||||
const centerX =
|
||||
canvasWidth !== undefined ? canvasWidth / 2 : canvas.width / 2;
|
||||
|
||||
ctx.font = 'bold 64px "Microsoft Yahei"';
|
||||
ctx.fillStyle = '#000';
|
||||
ctx.textAlign = 'center';
|
||||
ctx.fillText(appName + ' ' + title, canvas.width / 2, titleY);
|
||||
ctx.fillText(appName + ' ' + title, centerX, titleY);
|
||||
|
||||
// 调用回调函数,让调用者设置 currentY 并绘制分割线
|
||||
if (onHeaderDrawn) {
|
||||
|
||||
@@ -62,7 +62,7 @@ export function recordShareSuccess(): void {
|
||||
*/
|
||||
export function shouldShowShareGuide(): boolean {
|
||||
// TODO: 开启分享引导
|
||||
// return true;
|
||||
return false;
|
||||
// 如果今天已经分享过,不需要显示引导
|
||||
if (hasSharedToday()) {
|
||||
return false;
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
{
|
||||
"name": "mathPages/numberColor/numberColor",
|
||||
"pathName": "mathPages/numberColor/numberColor",
|
||||
"query": "id=number-find-color",
|
||||
"query": "id=number-write",
|
||||
"scene": null,
|
||||
"launchMode": "default"
|
||||
},
|
||||
|
||||