效果展示图:
这个项目主要的难点在于api的调用,只有俩个页面,页面布局相对简单一些.
1.通过百度翻译开放平台,申请百度翻译开发者账号,获取百度翻译中通用翻译API服务的相关信息.
2.构建翻译首页:
index.wxml:
<!--index.wxml-->
<view class='container'>
<view class='to-change-page'>
<navigator
url='/pages/change/change'
>
<text class='lang'>翻译成{{curLang.chinese}}</text>
<text class='iconfont icon-down'></text>
</navigator>
</view>
<view class='input-area'>
<view class='textarea-container'>
<textarea
placeholder='请输入要翻译的文本'
placeholder-style='color: #8995a1;'
value='{{query}}'
bindinput='onInput'
bindconfirm='onConfirm'
></textarea>
<text class='iconfont icon-close'
bindtap='onTapClose'
hidden='{{hideCloseIcon}}'
></text>
</view>
</view>
<button
bindtap='onConfirm'
>点击翻译</button>
<view class='output-area'>
<text class='title'>译文</text>
<view class='result-container'>
<view class='result'
wx:if='{{translateResult}}'
>{{translateResult}}</view>
</view>
</view>
<view class='copyright'>
<text>© 2019 strugglebak</text>
</view>
</view>
index.js:
import {translate} from '../../utils/api.js'
const app = getApp()
Page({
data: {
curLang: {},
hideCloseIcon: true,
query: '',
translateResult: '',
},
onLoad: function (options) {
console.log('options query', options.query)
if (options.query) {
this.setData({
query: options.query
})
}
},
onShow: function () {
this.setData({
curLang: app.globalData.curLang
})
this.onConfirm();
},
onInput: function (e) {
this.setData({
query: e.detail.value
})
if (this.data.query.length > 0) {
this.setData({
hideCloseIcon: false
})
} else {
this.setData({
hideCloseIcon: true
})
}
},
onConfirm: function () {
translate(
this.data.query,
{
from: 'auto',
to: this.data.curLang.lang
}
).then(data=> {
let resultArray = []
for (let i=0; i<data.trans_result.length; i++) {
resultArray.push(data.trans_result[i])
}
console.log('resultArray', resultArray)
let src = []
let dst = []
resultArray.forEach(key=> {
src.push(key['src'])
dst.push(key['dst'])
})
let queryString = src
let resultString = dst
console.log(queryString, resultString)
this.setData({
translateResult: resultString
})
})
},
onTapClose: function () {
this.setData({
query: '',
hideCloseIcon: true,
translateResult: ''
})
}
})
index.wxss:
/**index.wxss**/
view.to-change-page {
display: flex;
align-items: center;
color: #8995a1;
font-size: 24rpx;
padding: 20rpx 40rpx;
}
navigator .iconfont {
font-size: 20rpx;
color: #8995a1;
}
/* view.input-area {
border-bottom: 1px solid #c7cee0;
} */
view.textarea-container {
background: white;
position: relative;
box-shadow:1px 2px 3px 4px #ccc
}
view.textarea-container textarea {
background: white;
padding: 30rpx;
padding-right: 0;
width: calc(100% - 110rpx);
font-size: 34rpx;
}
view.textarea-container .iconfont {
position: absolute;
top: 30rpx; right: 40rpx;
z-index: 999;
font-size: 40rpx;
color: #888;
}
view.output-area {
min-height: 180rpx;
background: white;
padding: 40rpx;
box-shadow:1px 2px 3px 4px #ccc
}
view.output-area text.title {
font-size: 28rpx;
color: #8995a1;
}
view.output-area .result-container {
padding: 20rpx 0;
font-size: 34rpx;
}
view.output-area .result {
word-break: break-all;
}
button {
margin: 20rpx 20rpx;
font-size: 32rpx;
position: relative;
}
button::after {
position: absolute;
content: '';
display: block;
border: 1px solid black;
top: 0; left: 0;
bottom: 0; right: 0;
transform-origin: 0 0;
z-index: 2;
}
view.copyright {
color: #999;
display: flex;
justify-content: center;
flex: 1;
align-items: flex-end;
font-size: 28rpx;
padding-bottom: 20rpx;
}
3.封装api接口:
api.js:
import md5 from './md5.min.js'
const appid = "20190217000267988"
const key = "3Y5ZIcch3mbq5fX6Q7EC"
const url = "https://fanyi-api.baidu.com/api/trans/vip/translate"
function translate(
q,
{ from = 'auto', to = 'en' } = { from: 'auto', to: 'en' },
)
{
return new Promise((resolve, reject)=> {
let salt = Date.now()
let sign = md5(`${appid}${q}${salt}${key}`)
wx.request({
url,
data: {
q, from, to, appid, salt, sign
},
success(response) {
let data = response.data
if (data && data.trans_result) {
resolve(data)
}
}
})
})
}
module.exports = {
translate: translate
}
3.引入md5.min.js文件:
4.构建change页面:
change.wxml:
<!-- change.wxml -->
<view class='container'>
<text class='title'>翻译成</text>
<view class='lang-list'>
<view class='lang-wrapper'>
<view class='item'
wx:for='{{langList}}'
wx:key='index'
wx:for-item='langItem'
bindtap='onTapItem'
data-index='{{index}}'
data-lang='{{langItem.lang}}'
data-chinese='{{langItem.chinese}}'
>
<view class='lang'>{{langItem.chinese}}</view>
<text class='iconfont icon-ok'
wx:if='{{index===curLang.index}}'
></text>
</view>
</view>
</view>
</view>
change.js:
// pages/change/change.js
const app = getApp();
Page({
/**
* 页面的初始数据
*/
data: {
curLang: {},
langList: app.globalData.langList
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
this.setData({
curLang: app.globalData.curLang
})
},
/**
* onTapItem--监听 change 页 item 项被 tap
*/
onTapItem: function (e) {
let langObject = e.currentTarget.dataset
console.log(langObject)
// 本地设置
this.setData({
curLang: langObject
})
// 全局设置
app.globalData.curLang = langObject
wx.switchTab({
url: '/pages/index/index'
})
}
})
change.wxss:
/* change.wxss */
/* change.wxss */
.container {
background: #f8f8f8;
}
.title {
background: white;
border-bottom: 1px solid #ececec;
padding: 20rpx 40rpx;
color: #aaa;
font-size: 28rpx;
}
.lang-wrapper {
padding-left: 40rpx;
}
.lang-wrapper .item {
padding: 20rpx 40rpx 20rpx 0;
background: white;
display: flex;
flex-direction: row;
align-items: center;
border-bottom: 1px solid #ececec;
font-size: 32rpx;
}
.item .lang {
flex: 1;
}
.item .iconfont {
margin-left: auto;
color: #aaa;
font-size: 28rpx;
}
5.构建翻译历史页面(history)
history.wxml:
<!-- history.wxml -->
<view class='container'>
<text class='history-title {{state}}'>翻译历史</text>
<scroll-view scroll-y class='history-result-list'>
<view class='history-result'
wx:for='{{history}}'
wx:for-item='historyItem'
wx:key='index'
bindtap='onTapReLaunch'
data-query='{{historyItem.query}}'
>
<view class='orign-text'>{{historyItem.query}}</view>
<view class='tanslate-text'>{{historyItem.result}}</view>
</view>
</scroll-view>
</view>
history.js:
// pages/history/history.js
const app = getApp()
Page({
/**
* 页面的初始数据
*/
data: {
history: [],
state: ''
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
this.setData({
history: wx.getStorageSync('history')
})
let history = this.data.history
if (history && history.length > 0) {
this.setData({
state: 'stiky'
})
} else {
this.setData({
state: ''
})
}
},
onTapReLaunch: function (e) {
console.log('data-set', e.currentTarget.dataset)
let url = `/pages/index/index?query=${e.currentTarget.dataset.query}`
wx.reLaunch({
url
})
}
})
history.wxss:
/* history.wxss */
view.container {
padding: 40rpx 0;
display: flex;
height: 100vh;
}
.history-title {
font-size: 26rpx;
line-height: 38rpx;
color: #8995a1;
position: fixed;
top: 0; left: 0;
padding: 40rpx;
overflow: hidden;
width: 100%;
z-index: 999;
transition: all 0.3s;
}
.history-title.stiky {
background-color: white;
}
scroll-view.history-result-list {
margin-top: 50rpx;
background-color: #f5fafe;
}
view.history-result {
margin-top: 40rpx;
display: flex;
flex-direction: column;
}
view.history-result:last-child {
margin-bottom: 40rpx;
}
.orign-text {
color: #8995a1;
padding: 0 40rpx;
overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
}
.tanslate-text {
margin-top: 16rpx;
padding: 0 40rpx;
overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
}
app.js:
//app.js
App({
onLaunch: function () {
// 展示本地存储能力
this.globalData.curLang = wx.getStorageSync('curLang')
|| this.globalData.langList[0]
},
globalData: {
curLang: {},
langList: [
{
'lang': 'en',
'index': 0,
'chinese': '英文'
},
{
'lang': 'zh',
'index': 1,
'chinese': '中文'
},
{
'lang': 'jp',
'index': 2,
'chinese': '日语'
},
{
'lang': 'kor',
'index': 3,
'chinese': '韩语'
},
{
'lang': 'fra',
'index': 4,
'chinese': '法语'
},
{
'lang': 'spa',
'index': 5,
'chinese': '西班牙语'
},
{
'lang': 'ara',
'index': 6,
'chinese': '阿拉伯语'
}
]
}
})
app.json:
{
"pages": [
"pages/index/index",
"pages/history/history",
"pages/change/change"
],
"window": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#1c1b21",
"navigationBarTitleText": "翻译小助手",
"navigationBarTextStyle": "white"
},
"tabBar": {
"position": "top",
"color": "#595959",
"selectedColor": "#1c1b21",
"borderStyle": "white",
"list": [
{
"text": "翻译",
"pagePath": "pages/index/index"
},
{
"text": "历史",
"pagePath": "pages/history/history"
}
]
},
"sitemapLocation": "sitemap.json"
}