1.16更新

This commit is contained in:
zoujiandong 2026-01-16 10:58:35 +08:00
parent cf6df28e8c
commit 034744959f
13 changed files with 922 additions and 172 deletions

View File

@ -0,0 +1,91 @@
<template>
<view>
<!-- 当父组件传递的prop属性数据发生变化的时候 ,生成海报图片-->
<view :prop="domId" :change:prop="html2canvas.emitData" class="html2canvas">
<slot></slot>
</view>
</view>
</template>
<script>
import { base64ToPath } from '@/utils/image-tools.js';
export default {
props: {
domId: {
type: String,
required: true
}
},
mounted:function(){
console.log("组件加载完成");
},
methods: {
// renderjs
async receiveRenderData(imgData) {
let posterHeight=imgData.height;
let posterWidth=imgData.width;
let imgPath =await base64ToPath(imgData.imgVal, '.jpeg');
this.$emit('renderFinish', {"posterPath":imgPath,"posterHeight":posterHeight,"posterWidth":posterWidth});
uni.hideLoading();
},
showLoading() {
uni.showLoading({
title: "正在生成导出",
icon: "none",
mask: true,
duration: 3000
})
},
hideLoading() {
uni.hideLoading();
}
}
}
</script>
<script module="html2canvas" lang="renderjs">
import html2canvas from 'html2canvas';
export default {
data() {
return {
}
},
mounted:function(){
console.log("视图层渲染完成");
},
methods: {
// ,settimeout,
emitData(domId) {
this.$ownerInstance.callMethod('showLoading', true);
const dom = document.getElementById('poster');
console.log("dom",dom);
let width= dom.offsetWidth;
let height=dom.offsetHeight;
let windowHeight= uni.getSystemInfoSync().windowHeight;
let windowWidth=uni.getSystemInfoSync().windowWidth;
html2canvas(dom, {
width:width,
height:height,
//scale:2.5, //
scrollY: 0, // html2canvasscrollYscrollX0
scrollX: 0,
x:0,
y:0,
windowWidth:windowWidth,
windowHeight:windowHeight,
useCORS: true, //
}).then((canvas) => {
let imgVal= canvas.toDataURL('image/png');
this.$ownerInstance.callMethod('receiveRenderData',{imgVal:imgVal,height:height,width:width});
});
}
}
};
</script>
<style lang="scss">
</style>

View File

@ -0,0 +1,91 @@
<template>
<view>
<!-- 当父组件传递的prop属性数据发生变化的时候 ,生成海报图片-->
<view :prop="domId" :change:prop="html2canvas.emitData" class="html2canvas">
<slot></slot>
</view>
</view>
</template>
<script>
import { base64ToPath } from '@/utils/image-tools.js';
export default {
props: {
domId: {
type: String,
required: true
}
},
mounted:function(){
console.log("组件加载完成");
},
methods: {
// renderjs
async receiveRenderData(imgData) {
let posterHeight=imgData.height;
let posterWidth=imgData.width;
let imgPath =await base64ToPath(imgData.imgVal, '.jpeg');
this.$emit('renderFinish', {"posterPath":imgPath,"posterHeight":posterHeight,"posterWidth":posterWidth});
uni.hideLoading();
},
showLoading() {
uni.showLoading({
title: "正在生成导出",
icon: "none",
mask: true,
duration: 3000
})
},
hideLoading() {
uni.hideLoading();
}
}
}
</script>
<script module="html2canvas" lang="renderjs">
import html2canvas from 'html2canvas';
export default {
data() {
return {
}
},
mounted:function(){
console.log("视图层渲染完成");
},
methods: {
// ,settimeout,
emitData(domId) {
this.$ownerInstance.callMethod('showLoading', true);
const dom = document.getElementById('poster');
console.log("dom",dom);
let width= dom.offsetWidth;
let height=dom.offsetHeight;
let windowHeight= uni.getSystemInfoSync().windowHeight;
let windowWidth=uni.getSystemInfoSync().windowWidth;
html2canvas(dom, {
width:width,
height:height,
//scale:2.5, //
scrollY: 0, // html2canvasscrollYscrollX0
scrollX: 0,
x:0,
y:0,
windowWidth:windowWidth,
windowHeight:windowHeight,
useCORS: true, //
}).then((canvas) => {
let imgVal= canvas.toDataURL('image/png');
this.$ownerInstance.callMethod('receiveRenderData',{imgVal:imgVal,height:height,width:width});
});
}
}
};
</script>
<style lang="scss">
</style>

View File

@ -12,6 +12,7 @@
"@xkit-yx/utils": "^0.7.2",
"crypto-js": "^4.2.0",
"dayjs": "^1.11.18",
"html2canvas": "^1.4.1",
"image-tools": "^1.4.0",
"js-base64": "^3.7.8",
"js-md5": "^0.8.3",

View File

@ -76,6 +76,7 @@
msg: {
"price":res.data.amount,
"order_id":res.data.order_id,
"trade_no":res.data.trade_no,
'jifen':res.data.point,
},
});

View File

@ -1,8 +1,10 @@
<template>
<view class="my-code-page">
<webview src="https://dev-wx.igandan.com/expert/expertcodeimg?expert_uuid=9UFkll2Xo57km6224XE&fromtype=doctor"></webview>
<navBar title="我的二维码" v-if="!jieping"/>
<!-- <sp-html2canvas-render :useCORS="true" :allowTaint="true" domId="render-dom" ref="renderRef" @renderOver="renderOver"></sp-html2canvas-render> -->
<view class="my-code-page renderDom" id="render-dom" :class="{'active':jieping}">
<!-- <webview src="https://dev-wx.igandan.com/expert/expertcodeimg?expert_uuid=9UFkll2Xo57km6224XE&fromtype=doctor"></webview> -->
<!-- 顶部导航栏 -->
<navBar title="我的二维码" />
<!-- 内容 -->
<scroll-view scroll-y class="page-scroll" id="pageContent">
@ -59,20 +61,25 @@
</scroll-view>
<!-- 底部保存按钮 -->
<view class="save-bar">
<view class="save-bar" v-if="!jieping">
<button class="save-btn" @click="onSave">保存到手机相册</button>
</view>
</view>
</template>
<script setup>
<script setup >
import { base64ToPath } from 'image-tools'
import navBar from '@/components/navBar/navBar.vue'
import { onShow } from "@dcloudio/uni-app";
import spHtml2canvasRender from '@/uni_modules/sp-html2canvas-render/components/sp-html2canvas-render/sp-html2canvas-render.vue'
import { ref } from 'vue';
import docUrl from '@/utils/docUrl'
import bgImg from "@/static/background.jpg"
import viewnkImg from "@/static/arr.png"
const userInfo = ref({})
const renderRef = ref(null)
const jieping = ref(false)
const goBack = () => {
uni.navigateBack();
};
@ -97,186 +104,67 @@ const handleSaveError = (err) => {
});
}
};
const onSave = () => {
// #ifdef APP-PLUS
// App
if (typeof plus === 'undefined') {
uni.showToast({ title: '当前环境不支持此功能', icon: 'none' });
return;
}
//
uni.showLoading({ title: '保存中...' });
//
let timeoutTimer = setTimeout(() => {
uni.hideLoading();
uni.showToast({
title: '操作超时,请重试',
icon: 'none',
duration: 2000
});
}, 15000); // 15
// webview
const currentWebview = plus.webview.currentWebview();
// 使 draw
currentWebview.draw({
bitmap: true,
success: (bitmap) => {
clearTimeout(timeoutTimer);
try {
// bitmap base64
const base64 = bitmap.toBase64DataURL('image/png', 1.0);
// base64
const base64Data = base64.indexOf(',') > -1 ? base64.split(',')[1] : base64;
//
const fileName = 'mycode_' + Date.now() + '.png';
const tempPath = `_doc/${fileName}`;
// 使 plus.io
plus.io.resolveLocalFileSystemURL('_doc', (entry) => {
entry.getFile(fileName, { create: true, exclusive: false }, (fileEntry) => {
fileEntry.createWriter((writer) => {
// base64 ArrayBuffer
const binaryString = atob(base64Data);
const len = binaryString.length;
const bytes = new Uint8Array(len);
for (let i = 0; i < len; i++) {
bytes[i] = binaryString.charCodeAt(i);
}
writer.onwriteend = () => {
// bitmap
bitmap.recycle();
//
const localPath = plus.io.convertLocalFileSystemURL(fileEntry.fullPath);
//
uni.saveImageToPhotosAlbum({
filePath: localPath,
success: () => {
uni.hideLoading();
uni.showToast({
title: '保存成功',
icon: 'success',
duration: 2000
});
},
fail: (err) => {
uni.hideLoading();
console.error('保存到相册失败:', err);
handleSaveError(err);
}
});
};
writer.onerror = (err) => {
uni.hideLoading();
console.error('写入文件失败:', err);
bitmap.recycle();
uni.showToast({
title: '保存失败,请重试',
icon: 'none',
duration: 2000
});
};
// Blob
try {
const blob = new Blob([bytes], { type: 'image/png' });
writer.write(blob);
} catch (e) {
// Blob ArrayBuffer
try {
writer.write(bytes.buffer);
} catch (e2) {
uni.hideLoading();
console.error('写入失败:', e2);
bitmap.recycle();
uni.showToast({
title: '保存失败,请重试',
icon: 'none',
duration: 2000
});
}
}
}, (err) => {
clearTimeout(timeoutTimer);
uni.hideLoading();
console.error('创建写入器失败:', err);
bitmap.recycle();
uni.showToast({
title: '保存失败,请重试',
icon: 'none',
duration: 2000
jieping.value = true //
const that = this
setTimeout(()=>{
var pages = getCurrentPages(); //
var page = pages[pages.length - 1];
var bitmap = null;
var currentWebview = page.$getAppWebview();
bitmap = new plus.nativeObj.Bitmap('amway_img');// webviewBitmap
currentWebview.draw(bitmap, function() {
let rand = Math.floor(Math.random() * 10000)
let saveUrl = '_doc/' + rand + 'a.jpg'
bitmap.save(saveUrl, {}, function(i) {
uni.saveImageToPhotosAlbum({
filePath: i.target,
success: function() {
uni.showToast({
title: '保存图片成功',
mask: false,
duration: 1500
});
});
}, (err) => {
clearTimeout(timeoutTimer);
uni.hideLoading();
console.error('获取文件失败:', err);
bitmap.recycle();
uni.showToast({
title: '保存失败,请重试',
icon: 'none',
duration: 2000
});
});
}, (err) => {
clearTimeout(timeoutTimer);
uni.hideLoading();
console.error('解析文件系统失败:', err);
bitmap.recycle();
uni.showToast({
title: '保存失败,请重试',
icon: 'none',
duration: 2000
jieping.value = false //
}
});
}, function(e) {
console.log('保存图片失败:' + JSON.stringify(e));
jieping.value = false //
});
} catch (error) {
clearTimeout(timeoutTimer);
uni.hideLoading();
console.error('处理失败:', error);
if (bitmap && bitmap.recycle) {
bitmap.recycle();
}
uni.showToast({
title: '保存失败,请重试',
icon: 'none',
duration: 2000
});
}
},
fail: (err) => {
clearTimeout(timeoutTimer);
uni.hideLoading();
console.error('截图失败:', err);
uni.showToast({
title: '截图失败,请重试',
icon: 'none',
duration: 2000
}, function(e) {
console.log('截屏绘制图片失败:' + JSON.stringify(e));
jieping.value = false //
});
}
});
// #endif
// #ifndef APP-PLUS
uni.showToast({ title: '此功能仅支持 App 端', icon: 'none' });
// #endif
},100)
};
// const onSave = () => {
// //jieping.value = true //
// renderRef.value.h2cRenderDom();
// };
const renderOver = (e) => {
// ebase64
console.log("==== renderOver :", e);
base64ToPath(e).then((res) => {
console.log("==== path :", res);
});
}
</script>
<style lang="scss" scoped>
.my-code-page {
min-height: 100vh;
background-color: #0d7dfd;
.active{
transform: scale(0.8);
margin-top: -calc(var(--status-bar-height) + 44px);
transition: all 0.3s ease-in-out;
}
}
.squrebox{
margin:0 30rpx;

View File

@ -292,6 +292,12 @@
};
const goAddPatient = () => {
// uni.sendNativeEvent('goExpertQrcodePage', {
// msg: "expertQrcodePage"
// },ret => {
// console.log(ret);
// })
navTo({
url: '/pages_app/myCode/myCode'
})

View File

@ -102,5 +102,6 @@

View File

@ -0,0 +1,57 @@
## 1.2.32024-09-19
1. 更新示例工程
## 1.2.22024-05-08
1. 修改util.js路径为@/uni_modules/sp-html2canvas-render/utils/index.js
## 1.2.12024-05-08
1. 更新示例工程
## 1.2.02024-04-30
1. 示例工程中示例二已更新解决截图模糊的问题,请参考
## 1.1.92024-04-30
1.更新示例工程
## 1.1.82024-04-30
1. 优化了报错提示
2. domId设为必填
## 1.1.72024-04-29
1. h2c配置项更新
## 1.1.62024-03-08
1. 更新示例工程
2. 更新文档
## 1.1.52024-02-29
1. 更新示例工程示例四:横向长截图
## 1.1.42024-02-27
1. 更新base64ToPath方法以供需要用临时路径保存文件的小伙伴见示例一中使用
## 1.1.32024-02-24
1. 更新示例工程示例3动态domid可动态选择单独导出指定dom
## 1.1.22024-02-06
1. 更新文档
## 1.1.12024-02-06
1. 重大更新,详见文档
2. 更新示例工程
## 1.1.02024-02-05
1. 更新文档
## 1.0.92024-02-05
1. 重要更新插件更新内置了urlToBase64工具方法图片报错toDataURL on HTMLCanvasElement或其他问题导致图片无法正常渲染的可以使用该工具方法将图片路径(支持网络路径和本地相对路径)转换为base64格式
## 1.0.82024-02-04
1. 更新示例工程
## 1.0.72024-01-24
1. 更新示例工程延迟渲染示例
## 1.0.62024-01-16
1. 更新示例工程
2. 更新文档
## 1.0.52024-01-15
1. 更新示例工程
## 1.0.42023-12-08
1. 更新html2canvas中部分配置
2. 重新上传示例工程还请麻烦用hbuilderx一键导入示例不要使用zip下载的方式
3. 更新文档说明很多人问toDataURL on HTMLCanvasElement的问题有的人哪怕直接使用实例工程也会报错有的人却一切正常我对此提供了部分解决方式。
## 1.0.32023-11-29
1.更新示例工程内联使用方式详见inner页面
## 1.0.22023-11-27
1.更新示例工程样例
## 1.0.12023-11-27
1.解决在vue2的ap真机环境下可能出现的报错
2.更新示例代码兼容vue2/3写法支持图片生成样例
## 1.0.02023-10-20
1. 组件更新使用方式详见README
2. 更新示例项目

View File

@ -0,0 +1,110 @@
<template>
<!-- prop是自定义的数据字段名要与chang后的保持一致h2cRender是renderjs的module名称 -->
<view class="sp-html2canvas-render" :prop="domId" :change:prop="h2cRender.watchDomId">
<slot></slot>
<text :prop="expOver" :change:prop="h2cRender.watchExpOver"></text>
</view>
</template>
<script>
export default {
props: {
// domid
domId: {
type: String,
default: '',
require: true
}
},
data() {
return {
expOver: 0,
// #ifdef VUE2
// #ifdef APP
// Vue2APPh2cRender
h2cRender: null
// #endif
// #endif
}
},
methods: {
renderOver(e) {
//
this.$emit('renderOver', e)
},
h2cRenderDom() {
// #ifdef H5
this.renderDom()
// #endif
// #ifndef H5
// expOverRenderJs
this.expOver++
// .....
// #endif
}
}
}
</script>
<!-- renderjs目前仅支持内联使用 -->
<script module="h2cRender" lang="renderjs">
import html2canvas from 'html2canvas';
export default {
data() {
return {
domIdValue: ''
}
},
methods: {
async renderDom() {
// appdomId,scriptdataprops
// ,script,data
try {
const el = document.getElementById(this.domIdValue);
if(!el) {
console.error('dom盒子未加载成功请先确保dom渲染完成再检查你的domId是否有误');
return
}
/**
* 配置说明
* 1. allowTaint:true和useCORS:true都是解决跨域问题的方式(不一定完全能解决跨域)不同的是使用allowTaint会对canvas造成污染导致无法使用canvas.toDataURL方法
* 2. 想要完美解决跨域还得需要后端服务器设置access-control-allow-origin: *允许资源跨域访问前端设置useCORS:true
* 2. scale通过放大倍率来调整画质清晰度但是只调整这一个参数可能不是最优解
*/
const canvas = await html2canvas(el, {
width: el.offsetWidth,
height: el.offsetHeight,
x: 0,
y: 0,
logging: true,
useCORS: true,
// allowTaint: true,
// async: false,
scale: 2, // 2
// foreignObjectRendering: true, //
});
const base64 = canvas.toDataURL('image/png', 1);
this.$ownerInstance.callMethod('renderOver', base64);
} catch(err) {
console.log('==== err :', err.message);
}
},
// ,script,data
watchDomId(newValue, oldValue, ownerInstance, instance) {
this.domIdValue = newValue
},
watchExpOver(newValue, oldValue, ownerInstance, instance) {
if(newValue !== 0){
//
this.renderDom()
}
}
}
}
</script>
<style>
.sp-html2canvas-render {
position: relative;
}
</style>

View File

@ -0,0 +1,86 @@
{
"id": "sp-html2canvas-render",
"displayName": "基于html2canvas和renderjs 指定盒子截图 截屏 截长屏",
"version": "1.2.3",
"description": "基于html2canvas和renderjs的页面指定盒子截图截屏可截长屏页面生成图片",
"keywords": [
"截图",
"截屏",
"截长屏",
"生成图片",
"html2canvas"
],
"repository": "",
"engines": {
"HBuilderX": "^3.8.0"
},
"dcloudext": {
"type": "component-vue",
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "插件不采集任何数据",
"permissions": "无"
},
"npmurl": ""
},
"uni_modules": {
"dependencies": [],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y",
"alipay": "n"
},
"client": {
"Vue": {
"vue2": "y",
"vue3": "y"
},
"App": {
"app-vue": "y",
"app-nvue": "u"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "y",
"Edge": "y",
"Firefox": "y",
"Safari": "y"
},
"小程序": {
"微信": "u",
"阿里": "u",
"百度": "u",
"字节跳动": "u",
"QQ": "u",
"钉钉": "u",
"快手": "u",
"飞书": "u",
"京东": "u"
},
"快应用": {
"华为": "u",
"联盟": "u"
}
}
}
}
}

View File

@ -0,0 +1,11 @@
# sp-html2canvas-render
### 文档迁移
> 防止文档失效,提供下列五个地址,内容一致
- [地址一](https://sonvee.github.io/sv-app-docs/docs-github/src/plugins/sp-html2canvas-render/sp-html2canvas-render.html)
- [地址二](https://sv-app-docs.pages.dev/src/plugins/sp-html2canvas-render/sp-html2canvas-render.html)
- [地址三](https://sv-app-docs.4everland.app/src/plugins/sp-html2canvas-render/sp-html2canvas-render.html)
- [地址四](https://sv-app-docs.vercel.app/src/plugins/sp-html2canvas-render/sp-html2canvas-render.html) (需要梯子)
- [地址五](https://static-mp-74bfcbac-6ba6-4f39-8513-8831390ff75a.next.bspapp.com/docs-uni/src/plugins/sp-html2canvas-render/sp-html2canvas-render.html) (有IP限制)

View File

@ -0,0 +1,255 @@
function getLocalFilePath(path) {
if (path.indexOf('_www') === 0 || path.indexOf('_doc') === 0 || path.indexOf('_documents') === 0 || path.indexOf(
'_downloads') === 0) {
return path
}
if (path.indexOf('file://') === 0) {
return path
}
if (path.indexOf('/storage/emulated/0/') === 0) {
return path
}
if (path.indexOf('/') === 0) {
let localFilePath = plus.io.convertAbsoluteFileSystem(path)
if (localFilePath !== path) {
return localFilePath
} else {
path = path.substr(1)
}
}
return '_www/' + path
}
function dataUrlToBase64(str) {
let array = str.split(',')
return array[array.length - 1]
}
let index = 0
function getNewFileId() {
return Date.now() + String(index++)
}
function biggerThan(v1, v2) {
let v1Array = v1.split('.')
let v2Array = v2.split('.')
let update = false
for (let index = 0; index < v2Array.length; index++) {
let diff = v1Array[index] - v2Array[index]
if (diff !== 0) {
update = diff > 0
break
}
}
return update
}
export function pathToBase64(path) {
return new Promise(function(resolve, reject) {
if (typeof window === 'object' && 'document' in window) {
if (typeof FileReader === 'function') {
let xhr = new XMLHttpRequest()
xhr.open('GET', path, true)
xhr.responseType = 'blob'
xhr.onload = function() {
if (this.status === 200) {
let fileReader = new FileReader()
fileReader.onload = function(e) {
resolve(e.target.result)
}
fileReader.onerror = reject
fileReader.readAsDataURL(this.response)
}
}
xhr.onerror = reject
xhr.send()
return
}
let canvas = document.createElement('canvas')
let c2x = canvas.getContext('2d')
let img = new Image
img.onload = function() {
canvas.width = img.width
canvas.height = img.height
c2x.drawImage(img, 0, 0)
resolve(canvas.toDataURL())
canvas.height = canvas.width = 0
}
img.onerror = reject
img.src = path
return
}
if (typeof plus === 'object') {
plus.io.resolveLocalFileSystemURL(getLocalFilePath(path), function(entry) {
entry.file(function(file) {
let fileReader = new plus.io.FileReader()
fileReader.onload = function(data) {
resolve(data.target.result)
}
fileReader.onerror = function(error) {
reject(error)
}
fileReader.readAsDataURL(file)
}, function(error) {
reject(error)
})
}, function(error) {
reject(error)
})
return
}
if (typeof wx === 'object' && wx.canIUse('getFileSystemManager')) {
wx.getFileSystemManager().readFile({
filePath: path,
encoding: 'base64',
success: function(res) {
resolve('data:image/png;base64,' + res.data)
},
fail: function(error) {
reject(error)
}
})
return
}
reject(new Error('not support'))
})
}
export function base64ToPath(base64) {
return new Promise(function(resolve, reject) {
if (typeof window === 'object' && 'document' in window) {
base64 = base64.split(',')
let type = base64[0].match(/:(.*?);/)[1]
let str = atob(base64[1])
let n = str.length
let array = new Uint8Array(n)
while (n--) {
array[n] = str.charCodeAt(n)
}
return resolve((window.URL || window.webkitURL).createObjectURL(new Blob([array], {
type: type
})))
}
let extName = base64.split(',')[0].match(/data\:\S+\/(\S+);/)
if (extName) {
extName = extName[1]
} else {
reject(new Error('base64 error'))
}
let fileName = getNewFileId() + '.' + extName
if (typeof plus === 'object') {
let basePath = '_doc'
let dirPath = 'uniapp_temp'
let filePath = basePath + '/' + dirPath + '/' + fileName
if (!biggerThan(plus.os.name === 'Android' ? '1.9.9.80627' : '1.9.9.80472', plus.runtime.innerVersion)) {
plus.io.resolveLocalFileSystemURL(basePath, function(entry) {
entry.getDirectory(dirPath, {
create: true,
exclusive: false,
}, function(entry) {
entry.getFile(fileName, {
create: true,
exclusive: false,
}, function(entry) {
entry.createWriter(function(writer) {
writer.onwrite = function() {
resolve(filePath)
}
writer.onerror = reject
writer.seek(0)
writer.writeAsBinary(dataUrlToBase64(base64))
}, reject)
}, reject)
}, reject)
}, reject)
return
}
let bitmap = new plus.nativeObj.Bitmap(fileName)
bitmap.loadBase64Data(base64, function() {
bitmap.save(filePath, {}, function() {
bitmap.clear()
resolve(filePath)
}, function(error) {
bitmap.clear()
reject(error)
})
}, function(error) {
bitmap.clear()
reject(error)
})
return
}
if (typeof wx === 'object' && wx.canIUse('getFileSystemManager')) {
let filePath = wx.env.USER_DATA_PATH + '/' + fileName
wx.getFileSystemManager().writeFile({
filePath: filePath,
data: dataUrlToBase64(base64),
encoding: 'base64',
success: function() {
resolve(filePath)
},
fail: function(error) {
reject(error)
}
})
return
}
reject(new Error('not support'))
})
}
/**
* 图片地址转换为base64格式图片
* @param {string} url 图片地址 网络地址 本地相对路径
* @param {string} type base64图片类型 默认png
*/
export function urlToBase64(url, type = 'png') {
let promises
// 网络地址 或者h5端本地相对路径 可使用request方式
promises = new Promise((resolve, reject) => {
uni.request({
url: url,
method: 'GET',
responseType: 'arraybuffer',
success: (res) => {
const base64 = `data:image/${type};base64,${uni.arrayBufferToBase64(res.data)}`
resolve(base64);
},
fail: (err) => {
reject(err);
},
})
})
// #ifdef APP
if (!url.startsWith('http')) {
// app真机本地相对路径
promises = new Promise((resolve, reject) => {
// 使用compressImage获取到安卓本地路径file:///...
uni.compressImage({
src: url,
quality: 100,
success: (res) => {
const tempUrl = res.tempFilePath
plus.io.resolveLocalFileSystemURL(tempUrl, (entry) => {
entry.file((e) => {
let fileReader = new plus.io.FileReader();
fileReader.onload = (r) => {
resolve(r.target.result)
}
fileReader.readAsDataURL(e)
})
})
},
fail: (err) => {
reject(err);
},
})
})
}
// #endif
return promises
}

152
utils/image-tools.js Normal file
View File

@ -0,0 +1,152 @@
function getLocalFilePath(path) {
if (path.indexOf('_www') === 0 || path.indexOf('_doc') === 0 || path.indexOf('_documents') === 0 || path.indexOf('_downloads') === 0) {
return path
}
if (path.indexOf('file://') === 0) {
return path
}
if (path.indexOf('/storage/emulated/0/') === 0) {
return path
}
if (path.indexOf('/') === 0) {
var localFilePath = plus.io.convertAbsoluteFileSystem(path)
if (localFilePath !== path) {
return localFilePath
} else {
path = path.substr(1)
}
}
return '_www/' + path
}
export function pathToBase64(path) {
return new Promise(function(resolve, reject) {
if (typeof window === 'object' && 'document' in window) {
if (typeof FileReader === 'function') {
var xhr = new XMLHttpRequest()
xhr.open('GET', path, true)
xhr.responseType = 'blob'
xhr.onload = function() {
if (this.status === 200) {
let fileReader = new FileReader()
fileReader.onload = function(e) {
resolve(e.target.result)
}
fileReader.onerror = reject
fileReader.readAsDataURL(this.response)
}
}
xhr.onerror = reject
xhr.send()
return
}
var canvas = document.createElement('canvas')
var c2x = canvas.getContext('2d')
var img = new Image
img.onload = function() {
canvas.width = img.width
canvas.height = img.height
c2x.drawImage(img, 0, 0)
resolve(canvas.toDataURL())
canvas.height = canvas.width = 0
}
img.onerror = reject
img.src = path
return
}
if (typeof plus === 'object') {
plus.io.resolveLocalFileSystemURL(getLocalFilePath(path), function(entry) {
entry.file(function(file) {
var fileReader = new plus.io.FileReader()
fileReader.onload = function(data) {
resolve(data.target.result)
}
fileReader.onerror = function(error) {
reject(error)
}
fileReader.readAsDataURL(file)
}, function(error) {
reject(error)
})
}, function(error) {
reject(error)
})
return
}
if (typeof wx === 'object' && wx.canIUse('getFileSystemManager')) {
wx.getFileSystemManager().readFile({
filePath: path,
encoding: 'base64',
success: function(res) {
resolve('data:image/png;base64,' + res.data)
},
fail: function(error) {
reject(error)
}
})
return
}
reject(new Error('not support'))
})
}
export function base64ToPath(base64, extName) {
return new Promise(function(resolve, reject) {
if (typeof window === 'object' && 'document' in window) {
base64 = base64.split(',')
var type = base64[0].match(/:(.*?);/)[1]
var str = atob(base64[1])
var n = str.length
var array = new Uint8Array(n)
while (n--) {
array[n] = str.charCodeAt(n)
}
return resolve((window.URL || window.webkitURL).createObjectURL(new Blob([array], { type: type })))
}
var fileName;
if (!extName) {
extName = base64.match(/data\:\S+\/(\S+);/)
if (extName) {
extName = extName[1]
} else {
reject(new Error('base64 error'))
}
fileName = Date.now() + '.' + extName;
} else {
fileName = Date.now() + extName;
}
if (typeof plus === 'object') {
var bitmap = new plus.nativeObj.Bitmap('bitmap' + Date.now())
bitmap.loadBase64Data(base64, function() {
var filePath = '_doc/uniapp_temp/' + fileName
bitmap.save(filePath, {}, function() {
bitmap.clear()
resolve(filePath)
}, function(error) {
bitmap.clear()
reject(error)
})
}, function(error) {
bitmap.clear()
reject(error)
})
return
}
if (typeof wx === 'object' && wx.canIUse('getFileSystemManager')) {
var filePath = wx.env.USER_DATA_PATH + '/' + fileName
wx.getFileSystemManager().writeFile({
filePath: filePath,
data: base64.replace(/^data:\S+\/\S+;base64,/, ''),
encoding: 'base64',
success: function() {
resolve(filePath)
},
fail: function(error) {
reject(error)
}
})
return
}
reject(new Error('not support'))
})
}