Skip to content

Commit ab95823

Browse files
author
sanfordsun
committed
fix: multi select
1 parent 1a54aa7 commit ab95823

File tree

2 files changed

+171
-36
lines changed

2 files changed

+171
-36
lines changed

miniprogram/packageAPI/pages/chattool/material_view/material_view.js

Lines changed: 144 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@ const mockData = {
1919
},
2020
{
2121
groupOpenID: '',
22-
type: 'text/message',
23-
content: '阿尔山的秋天很美',
22+
type: 'image/png',
23+
name: '图片名称',
24+
path: 'https://gips2.baidu.com/it/u=1651586290,17201034&fm=3028&app=3028&f=JPEG&fmt=auto&q=100&size=f600_800',
25+
size: '图片大小'
2426
},
2527
{
2628
groupOpenID: '',
@@ -44,20 +46,6 @@ const mockData = {
4446
path: 'https://res.wx.qq.com/wxdoc/dist/assets/img/demo.ef5c5bef.jpg',
4547
size: '图片大小'
4648
},
47-
{
48-
groupOpenID: '',
49-
type: 'image/png',
50-
name: '图片名称',
51-
path: '图片路径',
52-
size: '图片大小'
53-
},
54-
{
55-
groupOpenID: '',
56-
type: 'image/png',
57-
name: '图片名称',
58-
path: '图片路径',
59-
size: '图片大小'
60-
},
6149
{
6250
groupOpenID: '',
6351
type: 'text/message',
@@ -99,7 +87,9 @@ const mockData = {
9987

10088
Page({
10189
data: {
102-
materials: []
90+
materials: [],
91+
canvasWidth: 0,
92+
canvasHeight: 0
10393
},
10494

10595
onUnload() {
@@ -109,6 +99,7 @@ Page({
10999
},
110100

111101
onLoad() {
102+
this._forwardMaterials = []
112103
this.getMaterials()
113104
// this.formatMaterials(mockData.materials)
114105

@@ -136,6 +127,9 @@ Page({
136127
},
137128

138129
formatMaterials(forwardMaterials = []) {
130+
this._forwardMaterials = forwardMaterials
131+
this.triggerMergedImage()
132+
139133
const materials = []
140134
for (let item of forwardMaterials) {
141135
let recordType = ''
@@ -158,4 +152,136 @@ Page({
158152
})
159153
},
160154

161-
})
155+
async triggerMergedImage() {
156+
try {
157+
const tempFilePaths = this._forwardMaterials
158+
.filter(item => item.type.startsWith('image'))
159+
.map(item => item.path)
160+
console.info('tempFilePaths: ', tempFilePaths)
161+
const shareImagePath = await this.mergeImages(tempFilePaths)
162+
this.setData({
163+
shareImagePath,
164+
})
165+
console.info('shareImagePath: ', shareImagePath)
166+
167+
} catch (error) {
168+
console.error('mergeImages fail: ', error)
169+
}
170+
},
171+
172+
shareMergedImage() {
173+
if (!this.data.shareImagePath) {
174+
wx.showToast({
175+
title: '拼图失败',
176+
icon: 'none'
177+
})
178+
this.triggerMergedImage()
179+
return
180+
}
181+
wx.shareImageToGroup({
182+
imagePath: this.data.shareImagePath,
183+
needShowEntrance: false,
184+
complete(res) {
185+
console.info('shareImageToGroup: ', res)
186+
}
187+
})
188+
},
189+
190+
async mergeImages(tempFilePaths) {
191+
try {
192+
// 获取 canvas 节点
193+
const { node: canvas, width: cw, height: ch } = await this.getCanvasNode();
194+
195+
// 获取 2D 上下文
196+
const ctx = canvas.getContext('2d');
197+
198+
// 预加载所有图片
199+
const images = await this.loadAllImages(canvas, tempFilePaths);
200+
201+
// 绘制图片
202+
this.drawImages(ctx, images, 400);
203+
204+
// 生成临时文件
205+
return await this.canvasToTempFile(canvas);
206+
} catch (err) {
207+
console.error('合并失败:', err);
208+
return null;
209+
}
210+
},
211+
212+
// 获取 Canvas 节点(Promise 封装)
213+
getCanvasNode() {
214+
return new Promise((resolve, reject) => {
215+
wx.createSelectorQuery()
216+
.select('#myCanvas')
217+
.fields({ node: true, size: true })
218+
.exec(res => {
219+
if (res[0]) resolve(res[0]);
220+
else reject(new Error('Canvas 节点获取失败'));
221+
});
222+
});
223+
},
224+
225+
// 计算画布尺寸
226+
calculateLayout(paths) {
227+
const imgSize = 100;
228+
const spacing = 10;
229+
const perLine = 3;
230+
231+
const rows = Math.ceil(paths.length / perLine);
232+
return {
233+
canvasWidth: perLine * imgSize + (perLine - 1) * spacing,
234+
canvasHeight: rows * imgSize + (rows - 1) * spacing
235+
};
236+
},
237+
238+
// 加载所有图片(Web Image 对象)
239+
loadAllImages(canvas, paths) {
240+
return Promise.all(paths.map(url => {
241+
return new Promise((resolve, reject) => {
242+
const image = canvas.createImage();
243+
image.onload = () => resolve(image);
244+
image.onerror = reject;
245+
image.src = url; // 支持本地路径和网络图片
246+
});
247+
}));
248+
},
249+
250+
// 执行图片绘制
251+
drawImages(ctx, images, canvasWidth) {
252+
const imgSize = 100;
253+
const spacing = 10;
254+
const perLine = 3;
255+
256+
images.forEach((image, index) => {
257+
const row = Math.floor(index / perLine);
258+
const col = index % perLine;
259+
260+
const x = col * (imgSize + spacing);
261+
const y = row * (imgSize + spacing);
262+
263+
// 绘制图像(支持缩放裁剪)
264+
ctx.drawImage(
265+
image,
266+
0, 0, image.width, image.height, // 源图裁剪区域
267+
x, y, imgSize, imgSize // 画布绘制区域
268+
);
269+
});
270+
},
271+
272+
// Canvas 转临时文件
273+
canvasToTempFile(canvas) {
274+
return new Promise((resolve, reject) => {
275+
wx.canvasToTempFilePath({
276+
canvas: canvas,
277+
fileType: 'png',
278+
width: 400,
279+
height: 500,
280+
quality: 1,
281+
success: res => resolve(res.tempFilePath),
282+
fail: reject
283+
});
284+
});
285+
}
286+
287+
})

miniprogram/packageAPI/pages/chattool/material_view/material_view.wxml

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,36 @@
55
<view class="container page" data-weui-theme="{{theme}}">
66
<template is="head" data="{{title: '聊天内容展示'}}" />
77
<view class="page-body">
8-
<block wx:if="{{materials.length}}">
9-
<view class="chat-list">
10-
<block wx:for="{{materials}}" wx:key="messageId">
11-
<view class="chat-item">
12-
<view>消息 id: {{item.messageId}}</view>
13-
<view>消息类型: {{item.type}} </view>
14-
<block wx:if="{{item.recordType === 'text'}}">
15-
<view>消息内容: {{item.content}}</view>
16-
</block>
17-
<block wx:elif="{{item.recordType === 'image'}}">
18-
<image class="chat-img" src="{{item.path}}" mode="aspectFill"/>
19-
</block>
20-
<block wx:else>
21-
<view>文件路径: {{item.path}}</view>
22-
</block>
23-
</view>
24-
</block>
25-
</view>
8+
<block wx:if="{{shareImagePath}}">
9+
<image src="{{shareImagePath}}" mode="aspectFill"></image>
2610
</block>
11+
<button style="width: 100%;" type="primary" bind:tap="shareMergedImage">分享拼图</button>
12+
<block wx:if="{{materials.length}}">
13+
<view class="chat-list">
14+
<block wx:for="{{materials}}" wx:key="messageId">
15+
<view class="chat-item">
16+
<view>消息 id: {{item.messageId}}</view>
17+
<view>消息类型: {{item.type}} </view>
18+
<block wx:if="{{item.recordType === 'text'}}">
19+
<view>消息内容: {{item.content}}</view>
20+
</block>
21+
<block wx:elif="{{item.recordType === 'image'}}">
22+
<image class="chat-img" src="{{item.path}}" mode="aspectFill" />
23+
</block>
24+
<block wx:else>
25+
<view>文件路径: {{item.path}}</view>
26+
</block>
27+
</view>
28+
</block>
29+
</view>
30+
</block>
2731
</view>
2832
<template is="foot" />
2933
</view>
3034
</scroll-view>
3135

36+
<canvas
37+
type="2d"
38+
id="myCanvas"
39+
style="width: 400px; height: 500px;position:fixed;left:-999px;"
40+
></canvas>

0 commit comments

Comments
 (0)