import React from "react"; import { View, Text } from "@tarojs/components"; import Taro from "@tarojs/taro"; import uploadApi from "@/services/uploadFiles"; import "./upload-from-wx.scss"; import { CoverImageValue } from "."; export interface UploadFromWxProps { onAdd: ( images: CoverImageValue[], onFileUploaded: Promise<{ id: string; url: string }[]> ) => void; maxCount: number; } async function convert_to_jpg_and_compress( src: string, { width, height } ): Promise { const canvas = Taro.createOffscreenCanvas({ type: "2d", width, height }); const ctx = canvas.getContext("2d") as CanvasRenderingContext2D; const image = canvas.createImage(); await new Promise((resolve) => { image.onload = resolve; image.src = src; }); ctx.clearRect(0, 0, width, height); ctx.drawImage(image as unknown as CanvasImageSource, 0, 0, width, height); // const imageData = ctx.getImageData(0, 0, width, height) return new Promise((resolve, reject) => { Taro.canvasToTempFilePath({ canvas: canvas as unknown as Taro.Canvas, fileType: "png", quality: 0.7, success: (res) => resolve(res.tempFilePath), fail: reject, }); }); } async function compressImage(files) { const res: string[] = []; for (const file of files) { const compressed_image = await convert_to_jpg_and_compress(file.path, { width: file.width, height: file.height, }); res.push(compressed_image); } return res; } // 图片标准容器为 360 * 240 3:2 // 压缩后图片最大宽高 const IMAGE_MAX_SIZE = { width: 1080, height: 720, }; // 标准长宽比,判断标准 const STANDARD_ASPECT_RATIO = IMAGE_MAX_SIZE.width / IMAGE_MAX_SIZE.height; type ChoosenImageRes = { path: string; size: number; width: number; height: number; }; // 根据图片标准重新设置图片尺寸 async function onChooseImageSuccess(tempFiles) { const result: ChoosenImageRes[] = []; for (const tempFile of tempFiles) { const { width, height } = await Taro.getImageInfo({ src: tempFile.path }); const image_aspect_ratio = width / height; let fileRes: ChoosenImageRes = { path: tempFile.path, size: tempFile.size, width: 0, height: 0, }; // 如果图片长宽比小于标准长宽比,则依照图片高度以及图片最大高度来重新设置图片尺寸 if (image_aspect_ratio < STANDARD_ASPECT_RATIO) { fileRes = { ...fileRes, ...(height > IMAGE_MAX_SIZE.height ? { width: Math.floor(IMAGE_MAX_SIZE.height * image_aspect_ratio), height: IMAGE_MAX_SIZE.height, } : { width: Math.floor(height * image_aspect_ratio), height }), }; } else { fileRes = { ...fileRes, ...(width > IMAGE_MAX_SIZE.width ? { width: IMAGE_MAX_SIZE.width, height: Math.floor(IMAGE_MAX_SIZE.width / image_aspect_ratio), } : { width, height: Math.floor(width / image_aspect_ratio) }), }; } result.push(fileRes); } return result; } export default function UploadFromWx(props: UploadFromWxProps) { const { onAdd = () => void 0, maxCount = 9, // calc from parent } = props; const handleImportFromWx = () => { Taro.chooseImage({ count: maxCount, sizeType: ["original", "compressed"], sourceType: ["album", "camera"], }).then(async (res) => { const analyzedFiles = await onChooseImageSuccess(res.tempFiles); // cropping image to standard size const compressedTempFiles = await compressImage(analyzedFiles); let start = Date.now(); const files = compressedTempFiles.map((path) => ({ filePath: path, description: "封面图", tags: "cover", is_public: 1 as unknown as 0 | 1, id: (start++).toString(), })); const onFileUpdate = uploadApi.batchUpload(files).then((res) => { return res.map((item) => ({ id: item.id, url: item ? item.data.file_url : "", })); }); onAdd( files.map((item) => ({ id: item.id, url: item.filePath, })), onFileUpdate ); }); }; return ( 从相册添加 ); }