uni保存canvas图片_中文汉字注音,汉字转拼音,支持图片识别文字,支持结果转图下载,附上小程序核心源码...

“文字注音”小程序在微信、字节跳动、支付宝、QQ等小程序平台同步上线,微信、头条、抖音、支付宝、QQ中搜索“文字注音”即可获得。

一、功能

汉字转拼音,支持图片识别文字,支持结果转图下载。该款小程序能够轻松将文字注音后输出,无需授权,无需注册,即来即用。你还可以用它来识别图片中的文字后注音,或者随时拍照后识别文字再注音。同时支持注音完成后复制拼音,支持将结果保存成图片下载到手机本地。欢迎扫描下面的各平台得小程序码来尝试一下。

5e3696e097ff57164e6b5fdc1d878706.png

9a6c9431ae98c370b005ea4e8024bedd.png

二、平台小程序码

359e39b474ea1ab704ebf74de91a1fc1.png

三、核心源码:

原文链接:

中文汉字注音,汉字转拼音,支持图片识别文字,支持结果转图下载,附上小程序核心源码 | 文思齐远 | 分享你我他​www.i847.cn
ca586ab0b2906c7d9a9e19b49a85b9c3.png
<template>
	<view class="content" style="width:100%">
		<view class="uni-textarea" style="width: 95%;margin: 0 auto;">
			<textarea v-if="status==0" :value="value" @input="valueChange" :style="{'height':textareaHeight+'px'}"
			 placeholder="请在这里输入或者粘贴文字,支持上传图片自动识别文字,支持中文注音。" maxlength="-1" adjust-position="{{keyUp}}"
			  @focus="focusTextarea" @blur="blurTextarea" />

			<view v-if="status==1" :style="{'height':resultHeight+'px','width': '100%','overflow-y': 'scroll'}" id="result">
				<view class="uni-row" style="padding: 9px 2%;font-size: 14px;text-align: center;">
					<view v-for="(item,i) in list" v-if="item.pinyin!='enter'" v-bind:key="i" class="uni-flex uni-column" style="float: left;margin: 3px;">
						 <view class="flex-item" style="min-width: 1px;">{{item.pinyin}}</view>
						 <view class="flex-item">{{item.value}}</view>
					</view>
					<view v-else style="clear: both;"></view>
				</view>
			</view>
		</view>
		<view style="position: fixed;bottom: 15px;width: 100%;">
			<view v-if="status==0" style="width: 92%;margin: 0 auto;margin-bottom: 10px;font-size: 16px;color: #6495ED;">
				<text style="cursor: pointer;" @tap="fromImg('album')">图片识别</text>
				<text style="cursor: pointer;margin-left: 10px;" @tap="fromImg('camera')">拍照识别</text>
				<text style="font-size: 12px;color: #B2B2B2;">(上传图片不宜过大)</text>
			</view>
		
			<view class="uni-flex uni-row" style="width: 92%;margin: 0 auto;">
				<view v-if="status==0" class="flex-item" style="width: 70%;">
					<button type="primary" style="width: 99%;float: left;" @tap="zhuyin()">注音</button>
				</view>
				
				<view v-if="status==1" class="flex-item" style="width: 35%;">
					<button type="primary" style="width: 99%;float: left;" @tap="copy()">复制</button>
				</view>
				
				<view v-if="status==1" class="flex-item" style="width: 35%;">
					<button type="primary" style="width: 99%;float: right;" :loading="down" :disabled="down" @tap="save()">下载</button>
				</view>
				
			    <view class="flex-item"  style="width: 30%;">
			    	<button type="default" style="width: 90%;float: right;" @tap="reset()">清空</button>
			    </view>
				<view style="clear: both;"></view>
			</view>
		</view>
		<canvas canvas-id="canvas" :style="{'z-index': '-1','position': 'absolute','top': '0px','left': '0px','width': canvasWidth + 'px','height': canvasHeight + 'px'}" v-if="showCanvas"></canvas>
	</view>
</template>

<script>
	var bopomofo = require('../../static/bopomofo.min.js');
	export default {
		data() {
			return {
				value: '',
				status: 0,
				list:[] ,
				textareaHeight: 0,
				resultHeight: 0,
				baiduToken: {},
				showCanvas: false,
				down:false,
				canvasWidth:0,
				canvasHeight:0,
				pixelRatio :1,
				textareaStaticHeight:0,
				canvasStaticHeight:0,
				keyUp:false,
			}
		},
		onLoad() {
			this.reset();
		},
		onReady(){
			var _that = this;
			uni.getSystemInfo({
			    success: function (res) {
					var windowHeight = res.windowHeight;
					_that.textareaHeight = windowHeight - 115;
					_that.textareaStaticHeight = windowHeight - 115;
					_that.resultHeight = windowHeight - 70;
					_that.canvasWidth = res.windowWidth;
					_that.canvasHeight = res.windowHeight * 10;
					_that.canvasStaticHeight = res.windowHeight * 10;
					_that.pixelRatio = res.pixelRatio;
			    }
			});
			uni.getStorage({
			    key: 'baiduToken',
			    success: function (res) {
			        _that.baiduToken = res.data;
					var now =  new Date().getTime();
					if(!_that.baiduToken || now > _that.baiduToken.expires){
						_that.getBaiduToken();
					}
			    },
				fail:function(e) {
					_that.getBaiduToken();
				}
			});
			uni.showShareMenu();
		},
		methods: {
			focusTextarea:function(e){
				this.textareaHeight = 100;
			},
			blurTextarea:function(e){
				this.textareaHeight = this.textareaStaticHeight;
			},
			save:function(){
				var _that = this;
				_that.down = true;
				//先设置canvas得高度
				_that.canvasHeight = _that.canvasStaticHeight;
				_that.showCanvas = true;
				setTimeout(function(){
					var ctx = uni.createCanvasContext("canvas",_that);
					ctx.rect(0, 0, _that.canvasWidth, _that.canvasHeight);
					ctx.setFillStyle('white');
					ctx.fill();
					ctx.setFillStyle('black');
					// 字体大小
					ctx.setFontSize(14);
					var fontHeight = 14;
					// 宽度
					var width = _that.canvasWidth;
					// 横向间隔
					var transverse = 9;
					// 纵向小间隔
					var portraitSmall = 4;
					// 纵向大间隔
					var portraitBig = 7;
					// 外间距
					var padding = 20;
					// 横向距离累计
					var transverseCumulative = padding;
					// 纵向距离累计
					var portraitCumulative  = padding;
					var lineHeight = portraitSmall  + portraitBig + (fontHeight*2);
					for(var i=0;i<_that.list.length;i++){
						// canvas高度变化
						if(i==0){
							_that.canvasHeight = portraitCumulative + lineHeight;
							setTimeout(function(){},10);
						}
						var item = _that.list[i];
						var metrics = ctx.measureText(item.pinyin);
						var tempX = transverseCumulative + transverse + metrics.width;
						if(tempX > (width-padding) || item.pinyin=="enter"){
							transverseCumulative = padding;
							portraitCumulative = portraitCumulative + lineHeight;
							_that.canvasHeight = portraitCumulative + lineHeight;
							setTimeout(function(){},10);
						}
						if(item.pinyin!="enter"){
							var x1;
							if(transverseCumulative==padding){
								x1 = transverseCumulative;
							}else{
								x1 = transverseCumulative + transverse;
							}
							var y1 = portraitCumulative;
							ctx.fillText(item.pinyin, x1, y1);
							var x2 = x1;
							var y2 = y1 + portraitSmall + fontHeight;
							ctx.fillText(item.value,x2, y2);
							transverseCumulative = x1 + metrics.width;
						}
					}
					ctx.draw();
					setTimeout(function(){
						uni.canvasToTempFilePath({
						  width: _that.canvasWidth,
						  height:  _that.canvasHeight,
						  destWidth: _that.canvasWidth * _that.pixelRatio,
						  destHeight:  _that.canvasHeight * _that.pixelRatio,
						  canvasId: 'canvas',
						  success: function(res) {
							uni.saveImageToPhotosAlbum({
								filePath: res.tempFilePath,
								success:function(){
									uni.showToast({
										title:"保存成功"
									})
								},
								complete:function(){
									_that.showCanvas = false;
									_that.down = false;
								}
							});
						  },
						  fail:function(e){
							  console.log(e);
						  	_that.showCanvas = false;
						  	_that.down = false;
						  }
						})
					},100);
				},100);
			},
			getBaiduToken:function(){
				var _that = this;
				var now =  new Date().getTime();
				uni.request({
				    url: 'https://aip.baidubce.com/oauth/2.0/token', 
					method: 'GET',
				    data: {
				        grant_type: 'client_credentials',
						client_id: '',
						client_secret: '',
				    },
				    success: (res) => {
				        _that.baiduToken = {
							access_token:res.data.access_token,
							expires:(res.data.expires_in * 1000 + now - 24 * 60 * 60 * 1000)
						}
						uni.setStorage({
						    key: 'baiduToken',
						    data: _that.baiduToken,
						    success: function () {
						        
						    }
						});
				    }
				});
			},
			fromImg:function(type){
				var _that = this;
				uni.chooseImage({
				    count: 1, 
					sourceType: [type],
				    success: function (res) {
						uni.getFileSystemManager().readFile({
							filePath: res.tempFilePaths[0], 
							encoding: 'base64', 
							success: res => { 
								var base64 = res.data;
								uni.showLoading({
								    title: '上传中...',
									mask:true
								});
								uni.request({
								    url: 'https://aip.baidubce.com/rest/2.0/ocr/v1/general_basic', 
									method: 'POST',
								    header: {
										'Content-Type': 'application/x-www-form-urlencoded'
									},
								    data: {
								        access_token: _that.baiduToken.access_token,
										image: encodeURI(base64),
										detect_direction: true
								    },
								    success: (res) => {
										uni.hideLoading();
										if(res.data){
											var value = '';
											for(var i=0;i<res.data.words_result_num;i++){
												value += res.data.words_result[i].words + "n";
											}
											_that.value = value;
										}
								    }
								});
								
							},fail: (e) => {
								console.log(e);
							}
						})
				    }
				});
			},
			copy:function(){
				if(this.list.length>0){
					var data = "";
					for(var i=0;i<this.list.length;i++){
						if(this.list[i].pinyin==" "){
							data += this.list[i].value;
						}else if(this.list[i].pinyin=="enter"){
							data += "n";
						}else{
							data += this.list[i].pinyin + " ";
						}
					}
					uni.setClipboardData({
					    data: data,
					    success: function () {
					        uni.showToast({
					            title: '复制成功',
					            duration: 2000
					        });
					    }
					});
				}
			},
			zhuyin:function(){
				var _that = this;
				if(this.value!=''){
					// 敏感词过滤
					uni.request({
					    url: 'https://aip.baidubce.com/rest/2.0/solution/v1/text_censor/v2/user_defined', 
						method: 'POST',
					    header: {
							'Content-Type': 'application/x-www-form-urlencoded'
						},
					    data: {
					        access_token: _that.baiduToken.access_token,
							text: _that.value,
					    },
					    success: (res) => {
							if(res.data.conclusionType == 1){
								_that.zhuyinDo();
							}else{
								var checkList = res.data.data;
								var content = "";
								for(var i=0;i<checkList.length;i++){
									var checkItem = checkList[i];
									content += (i+1) + "、" + checkItem.msg.replace("不合规","的字词") + "n";
								}
								uni.showModal({
									title: "请删除后重试",
									content: content,
									showCancel: false
								})
								console.log(res.data);
							}
					    }
					});
				}
			},
			zhuyinDo:function(){
				var arr = this.value.split('');
				for(var i=0;i<arr.length;i++){
					var cur = arr[i];
					if(cur=="n" || cur=="↵"){
						this.list.push({
							value: "enter",
							pinyin: "enter"
						});
					}
					if(this.isChinese(cur)){
						var pinyin = bopomofo.pinyin(cur);
						if(pinyin==cur || pinyin=='null'){
							pinyin=" ";
						}
						var tmp = {
							value: cur,
							pinyin: pinyin
						}
						this.list.push(tmp);
					}
				}
				this.status = 1;
				this.value = "";
			},
			reset:function(){
				this.value = "";
				this.status = 0;
				this.list = [];
				this.showCanvas = false;
				this.down = false;
			},
			valueChange:function(e){
				this.value = e.detail.value;
			},
			isChinese:function(value){
				if (escape(value).indexOf( "%u" )<0) {
					return false;
				}
				return true;
			}
		}
	}
</script>

<style>
	@import "../../static/uni.css";  
</style>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值