V1.1.1
This commit is contained in:
parent
aba3c69153
commit
8b678de6b5
@ -4,3 +4,8 @@ import api from './api'
|
||||
export function indexCount(data) {
|
||||
return api.get('/crm/index/getCount', data, { login: false })
|
||||
}
|
||||
|
||||
export function indexChartCount(data) {
|
||||
return api.get('/crm/achievement/count', data, { login: false })
|
||||
}
|
||||
|
||||
|
10
api/user.js
10
api/user.js
@ -18,5 +18,15 @@ export function getFlowUsers(data) {
|
||||
return api.get('/crm/flow/flow-users', data, { login: true })
|
||||
}
|
||||
|
||||
export function updateUser(data) {
|
||||
return api.put('/system/user/profile/update', data, { login: true })
|
||||
}
|
||||
|
||||
|
||||
export function updateUserProfilePassword(data) {
|
||||
return api.put('/system/user/profile/update-password', data, { login: true })
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
//export const VUE_APP_API_URL = 'http://localhost:48081/admin-api'
|
||||
export const VUE_APP_API_URL = 'https://apicrm.yixiang.co/admin-api'
|
||||
export const VUE_APP_API_URL = 'http://localhost:48081/admin-api'
|
||||
//export const VUE_APP_API_URL = 'https://apicrm.yixiang.co/admin-api'
|
||||
export const VUE_APP_RESOURCES_URL = 'https://h5.yixiang.co/static'
|
||||
export const VUE_APP_UPLOAD_URL = VUE_APP_API_URL + '/infra/file/upload'
|
||||
export const VUE_APP_UPLOAD_URL2 = VUE_APP_API_URL + '/system/user/profile/update-avatar'
|
||||
export const APP_ID = 'wxc061dee8806ff712'
|
||||
//export const APP_ID = 'wxdbdbc123c8c30b45'
|
||||
export const TENANT_ID = 1 //租户ID
|
||||
|
18
pages.json
18
pages.json
@ -298,6 +298,24 @@
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
|
||||
},
|
||||
{
|
||||
"path" : "pages/mine/edit",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText": "修改个人信息",
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
|
||||
},
|
||||
{
|
||||
"path" : "pages/mine/pass",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText": "修改密码",
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
|
||||
},
|
||||
{
|
||||
"path" : "pages/msg/wait",
|
||||
|
174
pages/components/pages/mine/edit.vue
Normal file
174
pages/components/pages/mine/edit.vue
Normal file
@ -0,0 +1,174 @@
|
||||
<template>
|
||||
<layout>
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<uv-navbar
|
||||
:fixed="false"
|
||||
:title="title"
|
||||
left-arrow
|
||||
@leftClick="$onClickLeft"
|
||||
/>
|
||||
<!-- #endif -->
|
||||
<view class="bg-white my-2">
|
||||
<uv-cell-group :border="false">
|
||||
<uv-cell :border="false">
|
||||
<!-- 自定义右侧值 -->
|
||||
<template v-slot:value>
|
||||
<text @click="selectFile" style="font-size: 26rpx;">修改头像</text>
|
||||
</template>
|
||||
<!-- 自定义左侧图标 -->
|
||||
<template v-slot:icon>
|
||||
<uv-avatar :src="avatar"></uv-avatar>
|
||||
<!-- <uv-icon size="60rpx" name="/static/images/16.png"></uv-icon> -->
|
||||
</template>
|
||||
<!-- 自定义右侧图标 -->
|
||||
<template v-slot:right-icon>
|
||||
<uv-icon size="30rpx" name="arrow-right"></uv-icon>
|
||||
</template>
|
||||
</uv-cell>
|
||||
</uv-cell-group>
|
||||
</view>
|
||||
<view style="background-color: #ffffff; padding: 0rpx 30rpx 30rpx 30rpx;">
|
||||
<uv-form labelPosition="left" :model="model1" :rules="rules" ref="uForm" labelWidth="60" :errorType="errorType" >
|
||||
<uv-form-item label="昵称" prop="nickname" borderBottom required>
|
||||
<uv-input v-model="model1.nickname" border="none">
|
||||
</uv-input>
|
||||
</uv-form-item>
|
||||
<uv-form-item label="手机号" prop="mobile" borderBottom required>
|
||||
<uv-input v-model="model1.mobile" border="none">
|
||||
</uv-input>
|
||||
</uv-form-item>
|
||||
<uv-form-item label="邮箱" prop="email" borderBottom>
|
||||
<uv-input v-model="model1.email" border="none">
|
||||
</uv-input>
|
||||
</uv-form-item>
|
||||
<uv-form-item label="性别" prop="sex" borderBottom @click="showSexSelect">
|
||||
<uv-radio-group v-model="model1.sex" >
|
||||
<uv-radio v-for="(item, index) in sexList" :key="index" :name="item.name" :customStyle="{margin: '8rpx'}" >
|
||||
{{ item.text }}
|
||||
</uv-radio>
|
||||
</uv-radio-group>
|
||||
</uv-form-item>
|
||||
<uv-button text="保存" customStyle="margin-top: 10px" color="#09b4f1" @click="submit"></uv-button>
|
||||
</uv-form>
|
||||
</view>
|
||||
</layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref
|
||||
} from 'vue'
|
||||
import { onLoad,onShow} from '@dcloudio/uni-app'
|
||||
import {
|
||||
updateUser
|
||||
} from '@/api/user'
|
||||
import { VUE_APP_UPLOAD_URL2 } from '@/config'
|
||||
import { formatDateTime } from '@/utils/util'
|
||||
import { useMainStore } from '@/store/store'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import cookie from '@/utils/cookie'
|
||||
const main = useMainStore()
|
||||
const { member } = storeToRefs(main)
|
||||
const title = ref('编辑个人信息')
|
||||
const errorType = ref('message')
|
||||
const rules = ref({
|
||||
'nickname': {
|
||||
type: 'string',
|
||||
required: true,
|
||||
message: '请填写昵称',
|
||||
trigger: ['blur', 'change']
|
||||
},
|
||||
'mobile': {
|
||||
type: 'string',
|
||||
required: true,
|
||||
message: '请填写手机号',
|
||||
trigger: ['blur', 'change']
|
||||
},
|
||||
})
|
||||
|
||||
const model1 = ref({
|
||||
nickname: member.value.nickname,
|
||||
mobile: member.value.mobile,
|
||||
email: member.value.email,
|
||||
sex: member.value.sex,
|
||||
})
|
||||
|
||||
const avatar = ref(member.value.avatar)
|
||||
|
||||
const sexList = ref([
|
||||
{
|
||||
name: 1,
|
||||
text: '男',
|
||||
},
|
||||
{
|
||||
name: 2,
|
||||
text: '女',
|
||||
},
|
||||
{
|
||||
name: 0,
|
||||
text: '未知',
|
||||
},
|
||||
])
|
||||
|
||||
onLoad((option) => {
|
||||
|
||||
})
|
||||
|
||||
const selectFile = () => {
|
||||
const token = cookie.get('accessToken')
|
||||
uni.chooseImage({
|
||||
count: 1,
|
||||
sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
|
||||
sourceType: ['album'], //从相册选择
|
||||
success: function (res) {
|
||||
uni.uploadFile({
|
||||
header:{
|
||||
Authorization: 'Bearer ' + token,
|
||||
},
|
||||
url:VUE_APP_UPLOAD_URL2,
|
||||
filePath: res.tempFilePaths[0],
|
||||
name: 'avatarFile',
|
||||
success: res => {
|
||||
console.log('res:',JSON.parse(res.data).data)
|
||||
avatar.value = JSON.parse(res.data).data
|
||||
},
|
||||
fail: e => {
|
||||
|
||||
},
|
||||
complete: res => {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const uForm = ref()
|
||||
const submit = () => {
|
||||
uForm.value.validate().then(res => {
|
||||
onSubmit()
|
||||
}).catch(errors => {
|
||||
uni.showToast({
|
||||
icon: 'error',
|
||||
title: '校验失败'
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const onSubmit = async() => {
|
||||
let data = await updateUser(model1.value)
|
||||
if (data) {
|
||||
uni.showToast({
|
||||
title: "保存成功",
|
||||
icon: 'success',
|
||||
duration: 2000
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
</style>
|
@ -13,7 +13,9 @@
|
||||
</uv-navbar>
|
||||
<view class="bg-white">
|
||||
<uv-cell-group>
|
||||
<uv-cell title="退出登录" :isLink="true" arrow-direction="right" @click="logout"></uv-cell>
|
||||
<uv-cell customStyle="padding:10rpx 0" title="修改个人信息" :isLink="true" arrow-direction="right" @click="gopage('/pages/components/pages/mine/edit')"></uv-cell>
|
||||
<uv-cell customStyle="padding:10rpx 0" title="修改密码" :isLink="true" arrow-direction="right" @click="gopage('/pages/components/pages/mine/pass')"></uv-cell>
|
||||
<uv-cell customStyle="padding:10rpx 0" title="退出登录" :isLink="true" arrow-direction="right" @click="logout"></uv-cell>
|
||||
</uv-cell-group>
|
||||
</view>
|
||||
</template>
|
||||
|
128
pages/components/pages/mine/pass.vue
Normal file
128
pages/components/pages/mine/pass.vue
Normal file
@ -0,0 +1,128 @@
|
||||
<template>
|
||||
<layout>
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<uv-navbar
|
||||
:fixed="false"
|
||||
:title="title"
|
||||
left-arrow
|
||||
@leftClick="$onClickLeft"
|
||||
/>
|
||||
<!-- #endif -->
|
||||
<view style="background-color: #ffffff; padding: 0rpx 30rpx 30rpx 30rpx;">
|
||||
<uv-form labelPosition="left" :model="model1" :rules="rules" ref="uForm" labelWidth="70" :errorType="errorType" >
|
||||
<uv-form-item label="旧密码" prop="oldPassword" borderBottom required>
|
||||
<uv-input v-model="model1.oldPassword" type="password" border="none">
|
||||
</uv-input>
|
||||
</uv-form-item>
|
||||
<uv-form-item label="新密码" prop="newPassword" borderBottom required>
|
||||
<uv-input v-model="model1.newPassword" type="password" border="none">
|
||||
</uv-input>
|
||||
</uv-form-item>
|
||||
<uv-form-item label="确认密码" prop="confirmPassword" borderBottom required>
|
||||
<uv-input v-model="model1.confirmPassword" type="password" border="none">
|
||||
</uv-input>
|
||||
</uv-form-item>
|
||||
<uv-button text="保存" customStyle="margin-top: 10px" color="#09b4f1" @click="submit"></uv-button>
|
||||
</uv-form>
|
||||
</view>
|
||||
</layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref
|
||||
} from 'vue'
|
||||
import { onLoad,onShow} from '@dcloudio/uni-app'
|
||||
import {
|
||||
updateUserProfilePassword
|
||||
} from '@/api/user'
|
||||
import {
|
||||
userLogout
|
||||
} from '@/api/auth'
|
||||
const title = ref('修改密码')
|
||||
const errorType = ref('message')
|
||||
const rules = ref({
|
||||
'oldPassword': {
|
||||
type: 'string',
|
||||
required: true,
|
||||
message: '请填写旧密码',
|
||||
trigger: ['blur', 'change']
|
||||
},
|
||||
'newPassword': {
|
||||
type: 'string',
|
||||
required: true,
|
||||
message: '请填写新密码',
|
||||
trigger: ['blur', 'change']
|
||||
},
|
||||
'confirmPassword': {
|
||||
type: 'string',
|
||||
required: true,
|
||||
message: '请确认密码',
|
||||
trigger: ['blur', 'change']
|
||||
},
|
||||
})
|
||||
|
||||
const model1 = ref({
|
||||
oldPassword: '',
|
||||
newPassword: '',
|
||||
confirmPassword: '',
|
||||
})
|
||||
|
||||
|
||||
onLoad((option) => {
|
||||
|
||||
})
|
||||
|
||||
const uForm = ref()
|
||||
const submit = () => {
|
||||
uForm.value.validate().then(res => {
|
||||
onSubmit()
|
||||
}).catch(errors => {
|
||||
uni.showToast({
|
||||
icon: 'error',
|
||||
title: '校验失败'
|
||||
})
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
const onSubmit = async() => {
|
||||
if(model1.value.newPassword != model1.value.confirmPassword){
|
||||
uni.showToast({
|
||||
icon: 'error',
|
||||
title: '输入密码不一致'
|
||||
})
|
||||
return
|
||||
}
|
||||
let data = await updateUserProfilePassword(model1.value)
|
||||
if (data) {
|
||||
uni.showToast({
|
||||
title: "保存成功",
|
||||
icon: 'success',
|
||||
duration: 2000
|
||||
})
|
||||
|
||||
logout()
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
const logout = async() => {
|
||||
await userLogout()
|
||||
setTimeout(() => {
|
||||
gopage('/pages/components/pages/login/login')
|
||||
}, 1500);
|
||||
|
||||
}
|
||||
|
||||
const gopage = (url) => {
|
||||
uni.navigateTo({
|
||||
url
|
||||
})
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
</style>
|
@ -46,6 +46,37 @@
|
||||
</uv-grid-item>
|
||||
</uv-grid>
|
||||
</view>
|
||||
<view class="region mt-3" style="margin-top: 20rpx;">
|
||||
<view class="title flex">
|
||||
<text>业绩目标</text>
|
||||
<view class="flex align-center">
|
||||
<uv-switch v-model="isContract" size="18" inactiveColor="#5ac725" @change="changeChart"></uv-switch>
|
||||
<view class="ml-1">
|
||||
<uv-text size="14" text="合同" color="#3c9cff" v-if="isContract"></uv-text>
|
||||
<uv-text size="14" text="回款" type="success" v-else></uv-text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<uv-row>
|
||||
<uv-col span="8">
|
||||
<qiun-data-charts
|
||||
type="gauge"
|
||||
:opts="opts"
|
||||
:chartData="chartData"
|
||||
/>
|
||||
</uv-col>
|
||||
<uv-col span="4">
|
||||
<view class="mb-4">
|
||||
<view class="text-color-assist font-size-medium mb-2">目标金额</view>
|
||||
<view>¥{{isContract ? chartCountData.contractMoney : chartCountData.receivablesMoney}}</view>
|
||||
</view>
|
||||
<view>
|
||||
<view class="text-color-assist font-size-medium mb-2">完成金额</view>
|
||||
<view>¥{{isContract ? chartCountData.contractSuccessMoney : chartCountData.receivablesSuccessMoney}}</view>
|
||||
</view>
|
||||
</uv-col>
|
||||
</uv-row>
|
||||
</view>
|
||||
|
||||
|
||||
|
||||
@ -58,7 +89,8 @@ import { onLoad,onShow} from '@dcloudio/uni-app'
|
||||
import { useMainStore } from '@/store/store'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import {
|
||||
indexCount
|
||||
indexCount,
|
||||
indexChartCount
|
||||
} from '@/api/index'
|
||||
const main = useMainStore()
|
||||
const statusBarHeight = ref(0)
|
||||
@ -201,11 +233,83 @@ const toolIcons3 = ref([
|
||||
])
|
||||
|
||||
|
||||
const chartData = ref(
|
||||
{
|
||||
categories: [{"value":0.2,"color":"#1890ff"},{"value":0.8,"color":"#2fc25b"},{"value":1,"color":"#f04864"}],
|
||||
series: [
|
||||
{
|
||||
name: "完成率",
|
||||
data: 0.2
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
const opts = ref(
|
||||
{
|
||||
color: ["#1890FF","#91CB74","#FAC858","#EE6666","#73C0DE","#3CA272","#FC8452","#9A60B4","#ea7ccc"],
|
||||
padding: undefined,
|
||||
title: {
|
||||
name: "完成率",
|
||||
fontSize: 25,
|
||||
color: "#2fc25b",
|
||||
offsetY: 0
|
||||
},
|
||||
subtitle: {
|
||||
name: "200%",
|
||||
fontSize: 15,
|
||||
color: "#1890ff",
|
||||
offsetY: 0
|
||||
},
|
||||
extra: {
|
||||
gauge: {
|
||||
type: "progress",
|
||||
width: 15,
|
||||
labelColor: "#666666",
|
||||
startAngle: 0.75,
|
||||
endAngle: 0.25,
|
||||
startNumber: 0,
|
||||
endNumber: 100,
|
||||
labelFormat: "",
|
||||
splitLine: {
|
||||
fixRadius: -10,
|
||||
splitNumber: 10,
|
||||
width: 15,
|
||||
color: "#FFFFFF",
|
||||
childNumber: 5,
|
||||
childWidth: 12
|
||||
},
|
||||
pointer: {
|
||||
width: 24,
|
||||
color: "auto"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
const isContract = ref(true)
|
||||
const chartCountData = ref({})
|
||||
|
||||
onShow(()=>{
|
||||
getData()
|
||||
getChart()
|
||||
})
|
||||
|
||||
const getChart = async() => {
|
||||
let data = await indexChartCount({type:2,year:2024,month:0})
|
||||
chartCountData.value = data
|
||||
let resData = data.contractPer
|
||||
chartData.value.series[0].data = resData > 100 ? 1 : resData/100
|
||||
opts.value.subtitle.name = resData+"%"
|
||||
}
|
||||
|
||||
const changeChart = () => {
|
||||
let resData = isContract.value ? chartCountData.value.contractPer : chartCountData.value.receivablesPer
|
||||
chartData.value.series[0].data = resData > 100 ? 1 : resData/100
|
||||
opts.value.subtitle.name = resData+"%"
|
||||
}
|
||||
|
||||
const getData = async() => {
|
||||
let data = await indexCount()
|
||||
let brieCount= data.brieCountVO
|
||||
|
@ -156,7 +156,7 @@ const orderTabs2 = [
|
||||
title: '公告',
|
||||
index: 1,
|
||||
image: '/static/images/11.png',
|
||||
path: ''
|
||||
path: '/pages/components/pages/mine/list'
|
||||
},
|
||||
{
|
||||
title: '跟进记录',
|
||||
|
225
uni_modules/lime-painter/changelog.md
Normal file
225
uni_modules/lime-painter/changelog.md
Normal file
@ -0,0 +1,225 @@
|
||||
## 1.9.6.6(2024-09-25)
|
||||
- fix: 修复background-position无效的问题
|
||||
## 1.9.6.5(2024-04-14)
|
||||
- fix: 修复`nvue`无法生图的问题
|
||||
## 1.9.6.4(2024-03-10)
|
||||
- fix: 修复代理ctx导致H5不能使用ctx.save
|
||||
## 1.9.6.3(2024-03-08)
|
||||
- fix: 修复支付宝真机无法使用的问题
|
||||
## 1.9.6.2(2024-02-22)
|
||||
- fix: 修复使用render函数报错的问题
|
||||
## 1.9.6.1(2023-12-22)
|
||||
- fix: 修复字节小程序非2d字体偏移
|
||||
- fix: 修复`canvasToTempFilePathSync`会触发两次的问题
|
||||
- fix: 修复`parser`图片没有宽度的问题
|
||||
## 1.9.6(2023-12-06)
|
||||
- fix: 修复背景图受padding影响
|
||||
- fix: 修复因字节报错改了代理实现导致微信报错
|
||||
- 1.9.5.8(2023-11-16)
|
||||
- fix: 修复margin问题
|
||||
- fix: 修复borderWidth问题
|
||||
- fix: 修复textBox问题
|
||||
- fix: 修复字节开发工具报`could not be cloned.`问题
|
||||
## 1.9.5.7(2023-07-27)
|
||||
- fix: 去掉多余的方法
|
||||
- chore: 更新文档,增加自定义字体说明
|
||||
## 1.9.5.6(2023-07-21)
|
||||
- feat: 有限的支持富文本
|
||||
- feat: H5和APP 增加 `hidpi` prop,主要用于大尺寸无法生成图片时用
|
||||
- fix: 修复 钉钉小程序 缺少 `measureText` 方法
|
||||
- chore: 由于微信小程序 pc 端的 canvas 2d 时不时抽风,故不使用canvas 2d
|
||||
## 1.9.5.5(2023-06-27)
|
||||
- fix: 修复把`emoji`表情字符拆分成多个字符的情况
|
||||
## 1.9.5.4(2023-06-05)
|
||||
- fix: 修复因`canvasToTempFilePathSync`监听导致重复调用
|
||||
## 1.9.5.3(2023-05-23)
|
||||
- fix: 因isPc错写成了isPC导致小程序PC不能生成图片
|
||||
## 1.9.5.2(2023-05-22)
|
||||
- feat: 删除多余文件
|
||||
## 1.9.5.1(2023-05-22)
|
||||
- fix: 修复 文字行数与`line-clamp`相同但不满一行时也加了省略号的问题
|
||||
## 1.9.5(2023-05-14)
|
||||
- feat: 增加 `text-indent` 和 `calc` 方法
|
||||
- feat: 优化 布局时间
|
||||
## 1.9.4.4(2023-04-15)
|
||||
- fix: 修复无法匹配负值
|
||||
- fix: 修复 Nvue IOS getImageInfo `useCORS` 为 undefined
|
||||
## 1.9.4.3(2023-04-01)
|
||||
- feat: 增加支持文字描边 `text-stroke: '5rpx #fff'`
|
||||
## 1.9.4.2(2023-03-30)
|
||||
- fix: 修复 支付宝小程序 isPC 在手机也为true的问题
|
||||
- feat: 由 微信开发工具 3060 版 无法获取图片尺寸,现 微信开发工具 3220 版 修复该问题,故还原上一版的获取图片方式。
|
||||
## 1.9.4.1(2023-03-28)
|
||||
- fix: 修复固定高度不正确问题
|
||||
## 1.9.4(2023-03-17)
|
||||
- fix: nvue ios getImageInfo缺少this报错
|
||||
- fix: pathType 非2d无效问题
|
||||
- fix: 修复 小米9se 可能会存在多次init 导致画面多次放大
|
||||
- fix: 修复 border 分开写 width style无效问题
|
||||
- fix: 修复 支付宝小程序IOS 再次进入不渲染的问题
|
||||
- fix: 修复 支付宝小程序安卓Zindex排序错乱问题
|
||||
- fix: 修复 微信开发工具 3060 版 无法获取图片的问题
|
||||
- feat: 把 for in 改为 forEach
|
||||
- feat: 增加 hidden
|
||||
- feat: 根节点 box-sizing 默认 `border-box`
|
||||
- feat: 增加支持 `vw` `wh`
|
||||
- chore: pathType 取消 默认值,因为字节开发工具不能显示
|
||||
- chore: 支付宝小程序开发工具不支持 生成图片 请以真机调试为准
|
||||
- bug: 企业微信 2.20.3无法使用
|
||||
## 1.9.3.5(2022-06-29)
|
||||
- feat: justifyContent 增加 `space-around`、`space-between`
|
||||
- feat: canvas 2d 也使用`getImageInfo`
|
||||
- fix: 修复 `text`的 `text-decoration`错位
|
||||
## 1.9.3.4(2022-06-20)
|
||||
- fix: 修复 因创建节点速度问题导致顺序出错。
|
||||
- fix: 修复 微信小程序 PC 无法显示本地图片
|
||||
- fix: 修复 flex-box 对齐问题
|
||||
- feat: 增加 `text-shadow`
|
||||
- feat: 重写 `text` 对齐方式
|
||||
- chore: 更新文档
|
||||
## 1.9.3.3(2022-06-17)
|
||||
- fix: 修复 支付宝小程序 canvas 2d 存在ctx.draw问题导致报错
|
||||
- fix: 修复 支付宝小程序 toDataURL 存在权限问题改用 `toTempFilePath`
|
||||
- fix: 修复 支付宝小程序 image size 问题导致 `objectFit` 无效
|
||||
## 1.9.3.2(2022-06-14)
|
||||
- fix: 修复 image 设置背景色不生效问题
|
||||
- fix: 修复 nvue 环境判断缺少参数问题
|
||||
## 1.9.3.1(2022-06-14)
|
||||
- fix: 修复 bottom 定位不对问题
|
||||
- fix: 修复 因小数导致计算出错换行问题
|
||||
- feat: 增加 `useCORS` h5端图片跨域 在设置请求头无效果后试一下设置这个值
|
||||
- chore: 更新文档
|
||||
## 1.9.3(2022-06-13)
|
||||
- feat: 增加 `zIndex`
|
||||
- feat: 增加 `flex-box` 该功能处于原始阶段,非常简陋。
|
||||
- tips: QQ小程序 vue3 不支持, 为 uni 官方BUG
|
||||
## 1.9.2.9(2022-06-10)
|
||||
- fix: 修复`text-align`及`margin`居中问题
|
||||
## 1.9.2.8(2022-06-10)
|
||||
- fix: 修复 Nvue `canvasToTempFilePathSync` 不生效问题
|
||||
## 1.9.2.7(2022-06-10)
|
||||
- fix: 修复 margin及padding的bug
|
||||
- fix: 修复 Nvue `isCanvasToTempFilePath` 不生效问题
|
||||
## 1.9.2.6(2022-06-09)
|
||||
- fix: 修复 Nvue 不显示
|
||||
- feat: 增加支持字体渐变
|
||||
```html
|
||||
<l-painter-text
|
||||
text="水调歌头\n明月几时有?把酒问青天。不知天上宫阙,今夕是何年。我欲乘风归去,又恐琼楼玉宇,高处不胜寒。起舞弄清影,何似在人间。"
|
||||
css="background: linear-gradient(,#ff971b 0%, #1989fa 100%); background-clip: text" />
|
||||
```
|
||||
## 1.9.2.5(2022-06-09)
|
||||
- chore: 更变获取父级宽度的设定
|
||||
- chore: `pathType` 在canvas 2d 默认为 `url`
|
||||
## 1.9.2.4(2022-06-08)
|
||||
- fix: 修复 `pathType` 不生效问题
|
||||
## 1.9.2.3(2022-06-08)
|
||||
- fix: 修复 `canvasToTempFilePath` 漏写 `success` 参数
|
||||
## 1.9.2.2(2022-06-07)
|
||||
- chore: 更新文档
|
||||
## 1.9.2.1(2022-06-07)
|
||||
- fix: 修复 vue3 赋值给this再传入导致image无法绘制
|
||||
- fix: 修复 `canvasToTempFilePathSync` 时机问题
|
||||
- feat: canvas 2d 更改图片生成方式 `toDataURL`
|
||||
## 1.9.2(2022-05-30)
|
||||
- fix: 修复 `canvasToTempFilePathSync` 在 vue3 下只生成一次
|
||||
## 1.9.1.7(2022-05-28)
|
||||
- fix: 修复 `qrcode`显示不全问题
|
||||
## 1.9.1.6(2022-05-28)
|
||||
- fix: 修复 `canvasToTempFilePathSync` 会重复多次问题
|
||||
- fix: 修复 `view` css `backgroundImage` 图片下载失败导致 子节点不渲染
|
||||
## 1.9.1.5(2022-05-27)
|
||||
- fix: 修正支付宝小程序 canvas 2d版本号 2.7.15
|
||||
## 1.9.1.4(2022-05-22)
|
||||
- fix: 修复字节小程序无法使用xml方式
|
||||
- fix: 修复字节小程序无法使用base64(非2D情况下工具上无法显示)
|
||||
- fix: 修复支付宝小程序 `canvasToTempFilePath` 报错
|
||||
## 1.9.1.3(2022-04-29)
|
||||
- fix: 修复vue3打包后uni对象为空后的报错
|
||||
## 1.9.1.2(2022-04-25)
|
||||
- fix: 删除多余文件
|
||||
## 1.9.1.1(2022-04-25)
|
||||
- fix: 修复图片不显示问题
|
||||
## 1.9.1(2022-04-12)
|
||||
- fix: 因四舍五入导致有些机型错位
|
||||
- fix: 修复无views报错
|
||||
- chore: nvue下因ios无法读取插件内static文件,改由下载方式
|
||||
## 1.9.0(2022-03-20)
|
||||
- fix: 因无法固定尺寸导致生成图片不全
|
||||
- fix: 特定情况下text判断无效
|
||||
- chore: 本地化APP Nvue webview
|
||||
## 1.8.9(2022-02-20)
|
||||
- fix: 修复 小程序下载最多10次并发的问题
|
||||
- fix: 修复 APP端无法获取本地图片
|
||||
- fix: 修复 APP Nvue端不执行问题
|
||||
- chore: 增加图片缓存机制
|
||||
## 1.8.8.8(2022-01-27)
|
||||
- fix: 修复 主动调用尺寸问题
|
||||
## 1.8.8.6(2022-01-26)
|
||||
- fix: 修复 nvue 下无宽度时获取父级宽度
|
||||
- fix: 修复 ios app 无法渲染问题
|
||||
## 1.8.8(2022-01-23)
|
||||
- fix: 修复 主动调用时无节点问题
|
||||
- fix: 修复 `box-shadow` 颜色问题
|
||||
- fix: 修复 `transform:rotate` 角度位置问题
|
||||
- feat: 增加 `overflow:hidden`
|
||||
## 1.8.7(2022-01-07)
|
||||
- fix: 修复 image 方向为 `right` 时原始宽高问题
|
||||
- feat: 支持 view 设置背景图 `background-image: url(xxx)`
|
||||
- chore: 去掉可选链
|
||||
## 1.8.6(2021-11-28)
|
||||
- feat: 支持`view`对`inline-block`的子集使用`text-align`
|
||||
## 1.8.5.5(2021-08-17)
|
||||
- chore: 更新文档,删除 replace
|
||||
- fix: 修复 text 值为 number时报错
|
||||
## 1.8.5.4(2021-08-16)
|
||||
- fix: 字节小程序兼容
|
||||
## 1.8.5.3(2021-08-15)
|
||||
- fix: 修复线性渐变与css现实效果不一致的问题
|
||||
- chore: 更新文档
|
||||
## 1.8.5.2(2021-08-13)
|
||||
- chore: 增加`background-image`、`background-repeat` 能力,主要用于背景纹理的绘制,并不是代替`image`。例如:大面积的重复平铺的水印
|
||||
- 注意:这个功能H5暂时无法使用,因为[官方的API有BUG](https://ask.dcloud.net.cn/question/128793),待官方修复!!!
|
||||
## 1.8.5.1(2021-08-10)
|
||||
- fix: 修复因`margin`报错问题
|
||||
## 1.8.5(2021-08-09)
|
||||
- chore: 增加margin支持`auto`,以达到居中效果
|
||||
## 1.8.4(2021-08-06)
|
||||
- chore: 增加判断缓存文件条件
|
||||
- fix: 修复css 多余空格报错问题
|
||||
## 1.8.3(2021-08-04)
|
||||
- tips: 1.6.x 以下的版本升级到1.8.x后要为每个元素都加上定位:position: 'absolute'
|
||||
- fix: 修复只有一个view子元素时不计算高度的问题
|
||||
## 1.8.2(2021-08-03)
|
||||
- fix: 修复 path-type 为 `url` 无效问题
|
||||
- fix: 修复 qrcode `text` 为空时报错问题
|
||||
- fix: 修复 image `src` 动态设置时不生效问题
|
||||
- feat: 增加 css 属性 `min-width` `max-width`
|
||||
## 1.8.1(2021-08-02)
|
||||
- fix: 修复无法加载本地图片
|
||||
## 1.8.0(2021-08-02)
|
||||
- chore 文档更新
|
||||
- 使用旧版的同学不要升级!
|
||||
## 1.8.0-beta(2021-07-30)
|
||||
- ## 全新布局方式 不兼容旧版!
|
||||
- chore: 布局方式变更
|
||||
- tips: 微信canvas 2d 不支持真机调试
|
||||
## 1.6.6(2021-07-09)
|
||||
- chore: 统一命名规范,无须主动引入组件
|
||||
## 1.6.5(2021-06-08)
|
||||
- chore: 去掉console
|
||||
## 1.6.4(2021-06-07)
|
||||
- fix: 修复 数字 为纯字符串时不转换的BUG
|
||||
## 1.6.3(2021-06-06)
|
||||
- fix: 修复 PC 端放大的BUG
|
||||
## 1.6.2(2021-05-31)
|
||||
- fix: 修复 报`adaptor is not a function`错误
|
||||
- fix: 修复 text 多行高度
|
||||
- fix: 优化 默认文字的基准线
|
||||
- feat: `@progress`事件,监听绘制进度
|
||||
## 1.6.1(2021-02-28)
|
||||
- 删除多余节点
|
||||
## 1.6.0(2021-02-26)
|
||||
- 调整为uni_modules目录规范
|
||||
- 修复:transform的rotate不能为负数问题
|
||||
- 新增:`pathType` 指定生成图片返回的路径类型,可选值有 `base64`、`url`
|
150
uni_modules/lime-painter/components/common/relation.js
Normal file
150
uni_modules/lime-painter/components/common/relation.js
Normal file
@ -0,0 +1,150 @@
|
||||
const styles = (v ='') => v.split(';').filter(v => v && !/^[\n\s]+$/.test(v)).map(v => {
|
||||
const key = v.slice(0, v.indexOf(':'))
|
||||
const value = v.slice(v.indexOf(':')+1)
|
||||
return {
|
||||
[key
|
||||
.replace(/-([a-z])/g, function() { return arguments[1].toUpperCase()})
|
||||
.replace(/\s+/g, '')
|
||||
]: value.replace(/^\s+/, '').replace(/\s+$/, '') || ''
|
||||
}
|
||||
})
|
||||
export function parent(parent) {
|
||||
return {
|
||||
provide() {
|
||||
return {
|
||||
[parent]: this
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
el: {
|
||||
id: null,
|
||||
css: {},
|
||||
views: []
|
||||
},
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
css: {
|
||||
handler(v) {
|
||||
if(this.canvasId) {
|
||||
this.el.css = (typeof v == 'object' ? v : v && Object.assign(...styles(v))) || {}
|
||||
this.canvasWidth = this.el.css && this.el.css.width || this.canvasWidth
|
||||
this.canvasHeight = this.el.css && this.el.css.height || this.canvasHeight
|
||||
}
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
export function children(parent, options = {}) {
|
||||
const indexKey = options.indexKey || 'index'
|
||||
return {
|
||||
inject: {
|
||||
[parent]: {
|
||||
default: null
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
el: {
|
||||
handler(v, o) {
|
||||
if(JSON.stringify(v) != JSON.stringify(o))
|
||||
this.bindRelation()
|
||||
},
|
||||
deep: true,
|
||||
immediate: true
|
||||
},
|
||||
src: {
|
||||
handler(v, o) {
|
||||
if(v != o)
|
||||
this.bindRelation()
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
text: {
|
||||
handler(v, o) {
|
||||
if(v != o) this.bindRelation()
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
css: {
|
||||
handler(v, o) {
|
||||
if(v != o)
|
||||
this.el.css = (typeof v == 'object' ? v : v && Object.assign(...styles(v))) || {}
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
replace: {
|
||||
handler(v, o) {
|
||||
if(JSON.stringify(v) != JSON.stringify(o))
|
||||
this.bindRelation()
|
||||
},
|
||||
deep: true,
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
created() {
|
||||
if(!this._uid) {
|
||||
this._uid = this._.uid
|
||||
}
|
||||
Object.defineProperty(this, 'parent', {
|
||||
get: () => this[parent] || [],
|
||||
})
|
||||
Object.defineProperty(this, 'index', {
|
||||
get: () => {
|
||||
this.bindRelation();
|
||||
const {parent: {el: {views=[]}={}}={}} = this
|
||||
return views.indexOf(this.el)
|
||||
},
|
||||
});
|
||||
this.el.type = this.type
|
||||
if(this.uid) {
|
||||
this.el.uid = this.uid
|
||||
}
|
||||
this.bindRelation()
|
||||
},
|
||||
// #ifdef VUE3
|
||||
beforeUnmount() {
|
||||
this.removeEl()
|
||||
},
|
||||
// #endif
|
||||
// #ifdef VUE2
|
||||
beforeDestroy() {
|
||||
this.removeEl()
|
||||
},
|
||||
// #endif
|
||||
methods: {
|
||||
removeEl() {
|
||||
if (this.parent) {
|
||||
this.parent.el.views = this.parent.el.views.filter(
|
||||
(item) => item._uid !== this._uid
|
||||
);
|
||||
}
|
||||
},
|
||||
bindRelation() {
|
||||
if(!this.el._uid) {
|
||||
this.el._uid = this._uid
|
||||
}
|
||||
if(['text','qrcode'].includes(this.type)) {
|
||||
this.el.text = this.$slots && this.$slots.default && this.$slots.default[0].text || `${this.text || ''}`.replace(/\\n/g, '\n')
|
||||
}
|
||||
if(this.type == 'image') {
|
||||
this.el.src = this.src
|
||||
}
|
||||
if (!this.parent) {
|
||||
return;
|
||||
}
|
||||
let views = this.parent.el.views || [];
|
||||
if(views.indexOf(this.el) !== -1) {
|
||||
this.parent.el.views = views.map(v => v._uid == this._uid ? this.el : v)
|
||||
} else {
|
||||
this.parent.el.views = [...views, this.el];
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// this.bindRelation()
|
||||
},
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
<template>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {parent, children} from '../common/relation';
|
||||
export default {
|
||||
name: 'lime-painter-image',
|
||||
mixins:[children('painter')],
|
||||
props: {
|
||||
id: String,
|
||||
css: [String, Object],
|
||||
src: String
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
type: 'image',
|
||||
el: {
|
||||
css: {},
|
||||
src: null
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
@ -0,0 +1,27 @@
|
||||
<template>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {parent, children} from '../common/relation';
|
||||
export default {
|
||||
name: 'lime-painter-qrcode',
|
||||
mixins:[children('painter')],
|
||||
props: {
|
||||
id: String,
|
||||
css: [String, Object],
|
||||
text: String
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
type: 'qrcode',
|
||||
el: {
|
||||
css: {},
|
||||
text: null
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
@ -0,0 +1,33 @@
|
||||
<template>
|
||||
<text style="opacity: 0;height: 0;"><slot/></text>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {parent, children} from '../common/relation';
|
||||
export default {
|
||||
name: 'lime-painter-text',
|
||||
mixins:[children('painter')],
|
||||
props: {
|
||||
type: {
|
||||
type: String,
|
||||
default: 'text'
|
||||
},
|
||||
uid: String,
|
||||
css: [String, Object],
|
||||
text: [String, Number],
|
||||
replace: Object,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// type: 'text',
|
||||
el: {
|
||||
css: {},
|
||||
text: null
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
@ -0,0 +1,34 @@
|
||||
<template>
|
||||
<view><slot/></view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {parent, children} from '../common/relation';
|
||||
export default {
|
||||
name: 'lime-painter-view',
|
||||
mixins:[children('painter'), parent('painter')],
|
||||
props: {
|
||||
id: String,
|
||||
type: {
|
||||
type: String,
|
||||
default: 'view'
|
||||
},
|
||||
css: [String, Object],
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// type: 'view',
|
||||
el: {
|
||||
css: {},
|
||||
views:[]
|
||||
},
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
461
uni_modules/lime-painter/components/l-painter/l-painter.vue
Normal file
461
uni_modules/lime-painter/components/l-painter/l-painter.vue
Normal file
@ -0,0 +1,461 @@
|
||||
<template>
|
||||
<view class="lime-painter" ref="limepainter">
|
||||
<view v-if="canvasId && size" :style="styles">
|
||||
<!-- #ifndef APP-NVUE -->
|
||||
<canvas class="lime-painter__canvas" v-if="use2dCanvas" :id="canvasId" type="2d" :style="size"></canvas>
|
||||
<canvas class="lime-painter__canvas" v-else :id="canvasId" :canvas-id="canvasId" :style="size"
|
||||
:width="boardWidth * dpr" :height="boardHeight * dpr" :hidpi="hidpi"></canvas>
|
||||
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef APP-NVUE -->
|
||||
<web-view :style="size" ref="webview"
|
||||
src="/uni_modules/lime-painter/hybrid/html/index.html"
|
||||
class="lime-painter__canvas" @pagefinish="onPageFinish" @error="onError" @onPostMessage="onMessage">
|
||||
</web-view>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
<slot />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { parent } from '../common/relation'
|
||||
import props from './props'
|
||||
import {toPx, base64ToPath, pathToBase64, isBase64, sleep, getImageInfo }from './utils';
|
||||
// #ifndef APP-NVUE
|
||||
import { canIUseCanvas2d, isPC} from './utils';
|
||||
import Painter from './painter';
|
||||
// import Painter from '@painter'
|
||||
const nvue = {}
|
||||
// #endif
|
||||
// #ifdef APP-NVUE
|
||||
import nvue from './nvue'
|
||||
// #endif
|
||||
export default {
|
||||
name: 'lime-painter',
|
||||
mixins: [props, parent('painter'), nvue],
|
||||
data() {
|
||||
return {
|
||||
use2dCanvas: false,
|
||||
canvasHeight: 150,
|
||||
canvasWidth: null,
|
||||
parentWidth: 0,
|
||||
inited: false,
|
||||
progress: 0,
|
||||
firstRender: 0,
|
||||
done: false,
|
||||
tasks: []
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
styles() {
|
||||
return `${this.size}${this.customStyle||''};` + (this.hidden && 'position: fixed; left: 1500rpx;')
|
||||
},
|
||||
canvasId() {
|
||||
return `l-painter${this._ && this._.uid || this._uid}`
|
||||
},
|
||||
size() {
|
||||
if (this.boardWidth && this.boardHeight) {
|
||||
return `width:${this.boardWidth}px; height: ${this.boardHeight}px;`;
|
||||
}
|
||||
},
|
||||
dpr() {
|
||||
return this.pixelRatio || uni.getSystemInfoSync().pixelRatio;
|
||||
},
|
||||
boardWidth() {
|
||||
const {width = 0} = (this.elements && this.elements.css) || this.elements || this
|
||||
const w = toPx(width||this.width)
|
||||
return w || Math.max(w, toPx(this.canvasWidth));
|
||||
},
|
||||
boardHeight() {
|
||||
const {height = 0} = (this.elements && this.elements.css) || this.elements || this
|
||||
const h = toPx(height||this.height)
|
||||
return h || Math.max(h, toPx(this.canvasHeight));
|
||||
},
|
||||
hasBoard() {
|
||||
return this.board && Object.keys(this.board).length
|
||||
},
|
||||
elements() {
|
||||
return this.hasBoard ? this.board : JSON.parse(JSON.stringify(this.el))
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.use2dCanvas = this.type === '2d' && canIUseCanvas2d() && !isPC
|
||||
},
|
||||
async mounted() {
|
||||
await sleep(30)
|
||||
await this.getParentWeith()
|
||||
this.$nextTick(() => {
|
||||
setTimeout(() => {
|
||||
this.$watch('elements', this.watchRender, {
|
||||
deep: true,
|
||||
immediate: true
|
||||
});
|
||||
}, 30)
|
||||
})
|
||||
},
|
||||
// #ifdef VUE3
|
||||
unmounted() {
|
||||
this.done = false
|
||||
this.inited = false
|
||||
this.firstRender = 0
|
||||
this.progress = 0
|
||||
this.painter = null
|
||||
clearTimeout(this.rendertimer)
|
||||
},
|
||||
// #endif
|
||||
// #ifdef VUE2
|
||||
destroyed() {
|
||||
this.done = false
|
||||
this.inited = false
|
||||
this.firstRender = 0
|
||||
this.progress = 0
|
||||
this.painter = null
|
||||
clearTimeout(this.rendertimer)
|
||||
},
|
||||
// #endif
|
||||
methods: {
|
||||
async watchRender(val, old) {
|
||||
if (!val || !val.views || (!this.firstRender ? !val.views.length : !this.firstRender) || !Object.keys(val).length || JSON.stringify(val) == JSON.stringify(old)) return;
|
||||
this.firstRender = 1
|
||||
this.progress = 0
|
||||
this.done = false
|
||||
clearTimeout(this.rendertimer)
|
||||
this.rendertimer = setTimeout(() => {
|
||||
this.render(val);
|
||||
}, this.beforeDelay)
|
||||
},
|
||||
async setFilePath(path, param) {
|
||||
let filePath = path
|
||||
const {pathType = this.pathType} = param || this
|
||||
if (pathType == 'base64' && !isBase64(path)) {
|
||||
filePath = await pathToBase64(path)
|
||||
} else if (pathType == 'url' && isBase64(path)) {
|
||||
filePath = await base64ToPath(path)
|
||||
}
|
||||
if (param && param.isEmit) {
|
||||
this.$emit('success', filePath);
|
||||
}
|
||||
return filePath
|
||||
},
|
||||
async getSize(args) {
|
||||
const {width} = args.css || args
|
||||
const {height} = args.css || args
|
||||
if (!this.size) {
|
||||
if (width || height) {
|
||||
this.canvasWidth = width || this.canvasWidth
|
||||
this.canvasHeight = height || this.canvasHeight
|
||||
await sleep(30);
|
||||
} else {
|
||||
await this.getParentWeith()
|
||||
}
|
||||
}
|
||||
},
|
||||
canvasToTempFilePathSync(args) {
|
||||
// this.stopWatch && this.stopWatch()
|
||||
// this.stopWatch = this.$watch('done', (v) => {
|
||||
// if (v) {
|
||||
// this.canvasToTempFilePath(args)
|
||||
// this.stopWatch && this.stopWatch()
|
||||
// }
|
||||
// }, {
|
||||
// immediate: true
|
||||
// })
|
||||
this.tasks.push(args)
|
||||
if(this.done){
|
||||
this.runTask()
|
||||
}
|
||||
},
|
||||
runTask(){
|
||||
while(this.tasks.length){
|
||||
const task = this.tasks.shift()
|
||||
this.canvasToTempFilePath(task)
|
||||
}
|
||||
},
|
||||
// #ifndef APP-NVUE
|
||||
getParentWeith() {
|
||||
return new Promise(resolve => {
|
||||
uni.createSelectorQuery()
|
||||
.in(this)
|
||||
.select(`.lime-painter`)
|
||||
.boundingClientRect()
|
||||
.exec(res => {
|
||||
const {width, height} = res[0]||{}
|
||||
this.parentWidth = Math.ceil(width||0)
|
||||
this.canvasWidth = this.parentWidth || 300
|
||||
this.canvasHeight = height || this.canvasHeight||150
|
||||
resolve(res[0])
|
||||
})
|
||||
})
|
||||
},
|
||||
async render(args = {}) {
|
||||
if(!Object.keys(args).length) {
|
||||
return console.error('空对象')
|
||||
}
|
||||
this.progress = 0
|
||||
this.done = false
|
||||
// #ifdef APP-NVUE
|
||||
this.tempFilePath.length = 0
|
||||
// #endif
|
||||
await this.getSize(args)
|
||||
const ctx = await this.getContext();
|
||||
|
||||
let {
|
||||
use2dCanvas,
|
||||
boardWidth,
|
||||
boardHeight,
|
||||
canvas,
|
||||
afterDelay
|
||||
} = this;
|
||||
if (use2dCanvas && !canvas) {
|
||||
return Promise.reject(new Error('canvas 没创建'));
|
||||
}
|
||||
this.boundary = {
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: boardWidth,
|
||||
height: boardHeight
|
||||
};
|
||||
this.painter = null
|
||||
if (!this.painter) {
|
||||
const {width} = args.css || args
|
||||
const {height} = args.css || args
|
||||
if(!width && this.parentWidth) {
|
||||
Object.assign(args, {width: this.parentWidth})
|
||||
}
|
||||
const param = {
|
||||
context: ctx,
|
||||
canvas,
|
||||
width: boardWidth,
|
||||
height: boardHeight,
|
||||
pixelRatio: this.dpr,
|
||||
useCORS: this.useCORS,
|
||||
createImage: getImageInfo.bind(this),
|
||||
performance: this.performance,
|
||||
listen: {
|
||||
onProgress: (v) => {
|
||||
this.progress = v
|
||||
this.$emit('progress', v)
|
||||
},
|
||||
onEffectFail: (err) => {
|
||||
this.$emit('faill', err)
|
||||
}
|
||||
}
|
||||
}
|
||||
this.painter = new Painter(param)
|
||||
}
|
||||
try{
|
||||
// vue3 赋值给data会引起图片无法绘制
|
||||
const { width, height } = await this.painter.source(JSON.parse(JSON.stringify(args)))
|
||||
this.boundary.height = this.canvasHeight = height
|
||||
this.boundary.width = this.canvasWidth = width
|
||||
await sleep(this.sleep);
|
||||
await this.painter.render()
|
||||
await new Promise(resolve => this.$nextTick(resolve));
|
||||
if (!use2dCanvas) {
|
||||
await this.canvasDraw();
|
||||
}
|
||||
if (afterDelay && use2dCanvas) {
|
||||
await sleep(afterDelay);
|
||||
}
|
||||
this.$emit('done');
|
||||
this.done = true
|
||||
if (this.isCanvasToTempFilePath) {
|
||||
this.canvasToTempFilePath()
|
||||
.then(res => {
|
||||
this.$emit('success', res.tempFilePath)
|
||||
})
|
||||
.catch(err => {
|
||||
this.$emit('fail', new Error(JSON.stringify(err)));
|
||||
});
|
||||
}
|
||||
this.runTask()
|
||||
return Promise.resolve({
|
||||
ctx,
|
||||
draw: this.painter,
|
||||
node: this.node
|
||||
});
|
||||
}catch(e){
|
||||
//TODO handle the exception
|
||||
}
|
||||
|
||||
},
|
||||
canvasDraw(flag = false) {
|
||||
return new Promise((resolve, reject) => this.ctx.draw(flag, () => setTimeout(() => resolve(), this
|
||||
.afterDelay)));
|
||||
},
|
||||
async getContext() {
|
||||
if (!this.canvasWidth) {
|
||||
this.$emit('fail', 'painter no size')
|
||||
console.error('[lime-painter]: 给画板或父级设置尺寸')
|
||||
return Promise.reject();
|
||||
}
|
||||
if (this.ctx && this.inited) {
|
||||
return Promise.resolve(this.ctx);
|
||||
}
|
||||
const { type, use2dCanvas, dpr, boardWidth, boardHeight } = this;
|
||||
const _getContext = () => {
|
||||
return new Promise(resolve => {
|
||||
uni.createSelectorQuery()
|
||||
.in(this)
|
||||
.select(`#${this.canvasId}`)
|
||||
.boundingClientRect()
|
||||
.exec(res => {
|
||||
if (res) {
|
||||
const ctx = uni.createCanvasContext(this.canvasId, this);
|
||||
if (!this.inited) {
|
||||
this.inited = true;
|
||||
this.use2dCanvas = false;
|
||||
this.canvas = res;
|
||||
}
|
||||
|
||||
// 钉钉小程序框架不支持 measureText 方法,用此方法 mock
|
||||
if (!ctx.measureText) {
|
||||
function strLen(str) {
|
||||
let len = 0;
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
if (str.charCodeAt(i) > 0 && str.charCodeAt(i) < 128) {
|
||||
len++;
|
||||
} else {
|
||||
len += 2;
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
ctx.measureText = text => {
|
||||
let fontSize = ctx.state && ctx.state.fontSize || 12;
|
||||
const font = ctx.__font
|
||||
if (font && fontSize == 12) {
|
||||
fontSize = parseInt(font.split(' ')[3], 10);
|
||||
}
|
||||
fontSize /= 2;
|
||||
return {
|
||||
width: strLen(text) * fontSize
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// #ifdef MP-ALIPAY
|
||||
ctx.scale(dpr, dpr);
|
||||
// #endif
|
||||
this.ctx = ctx
|
||||
resolve(this.ctx);
|
||||
} else {
|
||||
console.error('[lime-painter] no node')
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
if (!use2dCanvas) {
|
||||
return _getContext();
|
||||
}
|
||||
return new Promise(resolve => {
|
||||
uni.createSelectorQuery()
|
||||
.in(this)
|
||||
.select(`#${this.canvasId}`)
|
||||
.node()
|
||||
.exec(res => {
|
||||
let {node: canvas} = res && res[0]||{};
|
||||
if(canvas) {
|
||||
const ctx = canvas.getContext(type);
|
||||
if (!this.inited) {
|
||||
this.inited = true;
|
||||
this.use2dCanvas = true;
|
||||
this.canvas = canvas;
|
||||
}
|
||||
this.ctx = ctx
|
||||
resolve(this.ctx);
|
||||
} else {
|
||||
console.error('[lime-painter]: no size')
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
canvasToTempFilePath(args = {}) {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
const { use2dCanvas, canvasId, dpr, fileType, quality } = this;
|
||||
const success = async (res) => {
|
||||
try {
|
||||
const tempFilePath = await this.setFilePath(res.tempFilePath || res, args)
|
||||
const result = Object.assign(res, {tempFilePath})
|
||||
args.success && args.success(result)
|
||||
resolve(result)
|
||||
} catch (e) {
|
||||
this.$emit('fail', e)
|
||||
}
|
||||
}
|
||||
|
||||
let { top: y = 0, left: x = 0, width, height } = this.boundary || this;
|
||||
// let destWidth = width * dpr;
|
||||
// let destHeight = height * dpr;
|
||||
// #ifdef MP-ALIPAY
|
||||
// width = destWidth;
|
||||
// height = destHeight;
|
||||
// #endif
|
||||
|
||||
const copyArgs = Object.assign({
|
||||
// x,
|
||||
// y,
|
||||
// width,
|
||||
// height,
|
||||
// destWidth,
|
||||
// destHeight,
|
||||
canvasId,
|
||||
id: canvasId,
|
||||
fileType,
|
||||
quality,
|
||||
}, args, {success});
|
||||
// if(this.isPC || use2dCanvas) {
|
||||
// copyArgs.canvas = this.canvas
|
||||
// }
|
||||
if (use2dCanvas) {
|
||||
copyArgs.canvas = this.canvas
|
||||
try{
|
||||
// #ifndef MP-ALIPAY
|
||||
const oFilePath = this.canvas.toDataURL(`image/${args.fileType||fileType}`.replace(/pg/, 'peg'), args.quality||quality)
|
||||
if(/data:,/.test(oFilePath)) {
|
||||
uni.canvasToTempFilePath(copyArgs, this);
|
||||
} else {
|
||||
const tempFilePath = await this.setFilePath(oFilePath, args)
|
||||
args.success && args.success({tempFilePath})
|
||||
resolve({tempFilePath})
|
||||
}
|
||||
// #endif
|
||||
// #ifdef MP-ALIPAY
|
||||
this.canvas.toTempFilePath(copyArgs)
|
||||
// #endif
|
||||
}catch(e){
|
||||
args.fail && args.fail(e)
|
||||
reject(e)
|
||||
}
|
||||
} else {
|
||||
// #ifdef MP-ALIPAY
|
||||
if(this.ctx.toTempFilePath) {
|
||||
// 钉钉
|
||||
const ctx = uni.createCanvasContext(canvasId);
|
||||
ctx.toTempFilePath(copyArgs);
|
||||
} else {
|
||||
my.canvasToTempFilePath(copyArgs);
|
||||
}
|
||||
// #endif
|
||||
// #ifndef MP-ALIPAY
|
||||
uni.canvasToTempFilePath(copyArgs, this);
|
||||
// #endif
|
||||
}
|
||||
})
|
||||
}
|
||||
// #endif
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style>
|
||||
.lime-painter,
|
||||
.lime-painter__canvas {
|
||||
// #ifndef APP-NVUE
|
||||
width: 100%;
|
||||
// #endif
|
||||
// #ifdef APP-NVUE
|
||||
flex: 1;
|
||||
// #endif
|
||||
}
|
||||
</style>
|
214
uni_modules/lime-painter/components/l-painter/nvue.js
Normal file
214
uni_modules/lime-painter/components/l-painter/nvue.js
Normal file
@ -0,0 +1,214 @@
|
||||
// #ifdef APP-NVUE
|
||||
import {
|
||||
sleep,
|
||||
getImageInfo,
|
||||
isBase64,
|
||||
networkReg
|
||||
} from './utils';
|
||||
const dom = weex.requireModule('dom')
|
||||
import {
|
||||
version
|
||||
} from '../../package.json'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
tempFilePath: [],
|
||||
isInitFile: false,
|
||||
osName: uni.getSystemInfoSync().osName
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getParentWeith() {
|
||||
return new Promise(resolve => {
|
||||
dom.getComponentRect(this.$refs.limepainter, (res) => {
|
||||
this.parentWidth = Math.ceil(res.size.width)
|
||||
this.canvasWidth = this.canvasWidth || this.parentWidth || 300
|
||||
this.canvasHeight = res.size.height || this.canvasHeight || 150
|
||||
resolve(res.size)
|
||||
})
|
||||
})
|
||||
},
|
||||
onPageFinish() {
|
||||
this.webview = this.$refs.webview
|
||||
this.webview.evalJS(`init(${this.dpr})`)
|
||||
},
|
||||
onMessage(e) {
|
||||
const res = e.detail.data[0] || null;
|
||||
if (res.event) {
|
||||
if (res.event == 'inited') {
|
||||
this.inited = true
|
||||
}
|
||||
if (res.event == 'fail') {
|
||||
this.$emit('fail', res)
|
||||
}
|
||||
if (res.event == 'layoutChange') {
|
||||
const data = typeof res.data == 'string' ? JSON.parse(res.data) : res.data
|
||||
this.canvasWidth = Math.ceil(data.width);
|
||||
this.canvasHeight = Math.ceil(data.height);
|
||||
}
|
||||
if (res.event == 'progressChange') {
|
||||
this.progress = res.data * 1
|
||||
}
|
||||
if (res.event == 'file') {
|
||||
this.tempFilePath.push(res.data)
|
||||
if (this.tempFilePath.length > 7) {
|
||||
this.tempFilePath.shift()
|
||||
}
|
||||
return
|
||||
}
|
||||
if (res.event == 'success') {
|
||||
if (res.data) {
|
||||
this.tempFilePath.push(res.data)
|
||||
if (this.tempFilePath.length > 8) {
|
||||
this.tempFilePath.shift()
|
||||
}
|
||||
if (this.isCanvasToTempFilePath) {
|
||||
this.setFilePath(this.tempFilePath.join(''), {
|
||||
isEmit: true
|
||||
})
|
||||
}
|
||||
} else {
|
||||
this.$emit('fail', 'canvas no data')
|
||||
}
|
||||
return
|
||||
}
|
||||
this.$emit(res.event, JSON.parse(res.data));
|
||||
} else if (res.file) {
|
||||
this.file = res.data;
|
||||
} else {
|
||||
console.info(res[0])
|
||||
}
|
||||
},
|
||||
getWebViewInited() {
|
||||
if (this.inited) return Promise.resolve(this.inited);
|
||||
return new Promise((resolve) => {
|
||||
this.$watch(
|
||||
'inited',
|
||||
async val => {
|
||||
if (val) {
|
||||
resolve(val)
|
||||
}
|
||||
}, {
|
||||
immediate: true
|
||||
}
|
||||
);
|
||||
})
|
||||
},
|
||||
getTempFilePath() {
|
||||
if (this.tempFilePath.length == 8) return Promise.resolve(this.tempFilePath)
|
||||
return new Promise((resolve) => {
|
||||
this.$watch(
|
||||
'tempFilePath',
|
||||
async val => {
|
||||
if (val.length == 8) {
|
||||
resolve(val.join(''))
|
||||
}
|
||||
}, {
|
||||
deep: true
|
||||
}
|
||||
);
|
||||
})
|
||||
},
|
||||
getWebViewDone() {
|
||||
if (this.progress == 1) return Promise.resolve(this.progress);
|
||||
return new Promise((resolve) => {
|
||||
this.$watch(
|
||||
'progress',
|
||||
async val => {
|
||||
if (val == 1) {
|
||||
this.$emit('done')
|
||||
this.done = true
|
||||
this.runTask()
|
||||
resolve(val)
|
||||
}
|
||||
}, {
|
||||
immediate: true
|
||||
}
|
||||
);
|
||||
})
|
||||
},
|
||||
async render(args) {
|
||||
try {
|
||||
await this.getSize(args)
|
||||
const {
|
||||
width
|
||||
} = args.css || args
|
||||
if (!width && this.parentWidth) {
|
||||
Object.assign(args, {
|
||||
width: this.parentWidth
|
||||
})
|
||||
}
|
||||
const newNode = await this.calcImage(args);
|
||||
await this.getWebViewInited()
|
||||
this.webview.evalJS(`source(${JSON.stringify(newNode)})`)
|
||||
await this.getWebViewDone()
|
||||
await sleep(this.afterDelay)
|
||||
if (this.isCanvasToTempFilePath) {
|
||||
const params = {
|
||||
fileType: this.fileType,
|
||||
quality: this.quality
|
||||
}
|
||||
this.webview.evalJS(`save(${JSON.stringify(params)})`)
|
||||
}
|
||||
return Promise.resolve()
|
||||
} catch (e) {
|
||||
this.$emit('fail', e)
|
||||
}
|
||||
},
|
||||
async calcImage(args) {
|
||||
let node = JSON.parse(JSON.stringify(args))
|
||||
const urlReg = /url\((.+)\)/
|
||||
const {
|
||||
backgroundImage
|
||||
} = node.css || {}
|
||||
const isBG = backgroundImage && urlReg.exec(backgroundImage)[1]
|
||||
const url = node.url || node.src || isBG
|
||||
if (['text', 'qrcode'].includes(node.type)) {
|
||||
return node
|
||||
}
|
||||
if ((node.type === "image" || isBG) && url && !isBase64(url) && (this.osName == 'ios' || !networkReg
|
||||
.test(url))) {
|
||||
let {
|
||||
path
|
||||
} = await getImageInfo(url, true)
|
||||
if (isBG) {
|
||||
node.css.backgroundImage = `url(${path})`
|
||||
} else {
|
||||
node.src = path
|
||||
}
|
||||
} else if (node.views && node.views.length) {
|
||||
for (let i = 0; i < node.views.length; i++) {
|
||||
node.views[i] = await this.calcImage(node.views[i])
|
||||
}
|
||||
}
|
||||
return node
|
||||
},
|
||||
async canvasToTempFilePath(args = {}) {
|
||||
if (!this.inited) {
|
||||
return this.$emit('fail', 'no init')
|
||||
}
|
||||
this.tempFilePath = []
|
||||
if (args.fileType == 'jpg') {
|
||||
args.fileType = 'jpeg'
|
||||
}
|
||||
|
||||
this.webview.evalJS(`save(${JSON.stringify(args)})`)
|
||||
try {
|
||||
let tempFilePath = await this.getTempFilePath()
|
||||
|
||||
tempFilePath = await this.setFilePath(tempFilePath, args)
|
||||
args.success({
|
||||
errMsg: "canvasToTempFilePath:ok",
|
||||
tempFilePath
|
||||
})
|
||||
} catch (e) {
|
||||
console.log('e', e)
|
||||
args.fail({
|
||||
error: e
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// #endif
|
1
uni_modules/lime-painter/components/l-painter/painter.js
Normal file
1
uni_modules/lime-painter/components/l-painter/painter.js
Normal file
File diff suppressed because one or more lines are too long
56
uni_modules/lime-painter/components/l-painter/props.js
Normal file
56
uni_modules/lime-painter/components/l-painter/props.js
Normal file
@ -0,0 +1,56 @@
|
||||
export default {
|
||||
props: {
|
||||
board: Object,
|
||||
pathType: String, // 'base64'、'url'
|
||||
fileType: {
|
||||
type: String,
|
||||
default: 'png'
|
||||
},
|
||||
hidden: Boolean,
|
||||
quality: {
|
||||
type: Number,
|
||||
default: 1
|
||||
},
|
||||
css: [String, Object],
|
||||
// styles: [String, Object],
|
||||
width: [Number, String],
|
||||
height: [Number, String],
|
||||
pixelRatio: Number,
|
||||
customStyle: String,
|
||||
isCanvasToTempFilePath: Boolean,
|
||||
// useCanvasToTempFilePath: Boolean,
|
||||
sleep: {
|
||||
type: Number,
|
||||
default: 1000 / 30
|
||||
},
|
||||
beforeDelay: {
|
||||
type: Number,
|
||||
default: 100
|
||||
},
|
||||
afterDelay: {
|
||||
type: Number,
|
||||
default: 100
|
||||
},
|
||||
performance: Boolean,
|
||||
// #ifdef MP-WEIXIN || MP-TOUTIAO || MP-ALIPAY
|
||||
type: {
|
||||
type: String,
|
||||
default: '2d'
|
||||
},
|
||||
// #endif
|
||||
// #ifdef APP-NVUE
|
||||
hybrid: Boolean,
|
||||
timeout: {
|
||||
type: Number,
|
||||
default: 2000
|
||||
},
|
||||
// #endif
|
||||
// #ifdef H5 || APP-PLUS
|
||||
useCORS: Boolean,
|
||||
hidpi: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
// #endif
|
||||
}
|
||||
}
|
1
uni_modules/lime-painter/components/l-painter/single.js
Normal file
1
uni_modules/lime-painter/components/l-painter/single.js
Normal file
File diff suppressed because one or more lines are too long
368
uni_modules/lime-painter/components/l-painter/utils.js
Normal file
368
uni_modules/lime-painter/components/l-painter/utils.js
Normal file
@ -0,0 +1,368 @@
|
||||
export const networkReg = /^(http|\/\/)/;
|
||||
export const isBase64 = (path) => /^data:image\/(\w+);base64/.test(path);
|
||||
export function sleep(delay) {
|
||||
return new Promise(resolve => setTimeout(resolve, delay))
|
||||
}
|
||||
let {platform, SDKVersion} = uni.getSystemInfoSync()
|
||||
export const isPC = /windows|mac/.test(platform)
|
||||
// 缓存图片
|
||||
let cache = {}
|
||||
export function isNumber(value) {
|
||||
return /^-?\d+(\.\d+)?$/.test(value);
|
||||
}
|
||||
export function toPx(value, baseSize, isDecimal = false) {
|
||||
// 如果是数字
|
||||
if (typeof value === 'number') {
|
||||
return value
|
||||
}
|
||||
// 如果是字符串数字
|
||||
if (isNumber(value)) {
|
||||
return value * 1
|
||||
}
|
||||
// 如果有单位
|
||||
if (typeof value === 'string') {
|
||||
const reg = /^-?([0-9]+)?([.]{1}[0-9]+){0,1}(em|rpx|px|%)$/g
|
||||
const results = reg.exec(value);
|
||||
if (!value || !results) {
|
||||
return 0;
|
||||
}
|
||||
const unit = results[3];
|
||||
value = parseFloat(value);
|
||||
let res = 0;
|
||||
if (unit === 'rpx') {
|
||||
res = uni.upx2px(value);
|
||||
} else if (unit === 'px') {
|
||||
res = value * 1;
|
||||
} else if (unit === '%') {
|
||||
res = value * toPx(baseSize) / 100;
|
||||
} else if (unit === 'em') {
|
||||
res = value * toPx(baseSize || 14);
|
||||
}
|
||||
return isDecimal ? res.toFixed(2) * 1 : Math.round(res);
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// 计算版本
|
||||
export function compareVersion(v1, v2) {
|
||||
v1 = v1.split('.')
|
||||
v2 = v2.split('.')
|
||||
const len = Math.max(v1.length, v2.length)
|
||||
while (v1.length < len) {
|
||||
v1.push('0')
|
||||
}
|
||||
while (v2.length < len) {
|
||||
v2.push('0')
|
||||
}
|
||||
for (let i = 0; i < len; i++) {
|
||||
const num1 = parseInt(v1[i], 10)
|
||||
const num2 = parseInt(v2[i], 10)
|
||||
|
||||
if (num1 > num2) {
|
||||
return 1
|
||||
} else if (num1 < num2) {
|
||||
return -1
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
function gte(version) {
|
||||
// #ifdef MP-ALIPAY
|
||||
SDKVersion = my.SDKVersion
|
||||
// #endif
|
||||
return compareVersion(SDKVersion, version) >= 0;
|
||||
}
|
||||
export function canIUseCanvas2d() {
|
||||
// #ifdef MP-WEIXIN
|
||||
return gte('2.9.2');
|
||||
// #endif
|
||||
// #ifdef MP-ALIPAY
|
||||
return gte('2.7.15');
|
||||
// #endif
|
||||
// #ifdef MP-TOUTIAO
|
||||
return gte('1.78.0');
|
||||
// #endif
|
||||
return false
|
||||
}
|
||||
|
||||
// #ifdef MP
|
||||
export const prefix = () => {
|
||||
// #ifdef MP-TOUTIAO
|
||||
return tt
|
||||
// #endif
|
||||
// #ifdef MP-WEIXIN
|
||||
return wx
|
||||
// #endif
|
||||
// #ifdef MP-BAIDU
|
||||
return swan
|
||||
// #endif
|
||||
// #ifdef MP-ALIPAY
|
||||
return my
|
||||
// #endif
|
||||
// #ifdef MP-QQ
|
||||
return qq
|
||||
// #endif
|
||||
// #ifdef MP-360
|
||||
return qh
|
||||
// #endif
|
||||
}
|
||||
// #endif
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* base64转路径
|
||||
* @param {Object} base64
|
||||
*/
|
||||
export function base64ToPath(base64) {
|
||||
const [, format] = /^data:image\/(\w+);base64,/.exec(base64) || [];
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
// #ifdef MP
|
||||
const fs = uni.getFileSystemManager()
|
||||
//自定义文件名
|
||||
if (!format) {
|
||||
reject(new Error('ERROR_BASE64SRC_PARSE'))
|
||||
}
|
||||
const time = new Date().getTime();
|
||||
let pre = prefix()
|
||||
// #ifdef MP-TOUTIAO
|
||||
const filePath = `${pre.getEnvInfoSync().common.USER_DATA_PATH}/${time}.${format}`
|
||||
// #endif
|
||||
// #ifndef MP-TOUTIAO
|
||||
const filePath = `${pre.env.USER_DATA_PATH}/${time}.${format}`
|
||||
// #endif
|
||||
fs.writeFile({
|
||||
filePath,
|
||||
data: base64.split(',')[1],
|
||||
encoding: 'base64',
|
||||
success() {
|
||||
resolve(filePath)
|
||||
},
|
||||
fail(err) {
|
||||
console.error(err)
|
||||
reject(err)
|
||||
}
|
||||
})
|
||||
// #endif
|
||||
|
||||
// #ifdef H5
|
||||
// mime类型
|
||||
let mimeString = base64.split(',')[0].split(':')[1].split(';')[0];
|
||||
//base64 解码
|
||||
let byteString = atob(base64.split(',')[1]);
|
||||
//创建缓冲数组
|
||||
let arrayBuffer = new ArrayBuffer(byteString.length);
|
||||
//创建视图
|
||||
let intArray = new Uint8Array(arrayBuffer);
|
||||
for (let i = 0; i < byteString.length; i++) {
|
||||
intArray[i] = byteString.charCodeAt(i);
|
||||
}
|
||||
resolve(URL.createObjectURL(new Blob([intArray], {
|
||||
type: mimeString
|
||||
})))
|
||||
// #endif
|
||||
|
||||
// #ifdef APP-PLUS
|
||||
const bitmap = new plus.nativeObj.Bitmap('bitmap' + Date.now())
|
||||
bitmap.loadBase64Data(base64, () => {
|
||||
if (!format) {
|
||||
reject(new Error('ERROR_BASE64SRC_PARSE'))
|
||||
}
|
||||
const time = new Date().getTime();
|
||||
const filePath = `_doc/uniapp_temp/${time}.${format}`
|
||||
bitmap.save(filePath, {},
|
||||
() => {
|
||||
bitmap.clear()
|
||||
resolve(filePath)
|
||||
},
|
||||
(error) => {
|
||||
bitmap.clear()
|
||||
reject(error)
|
||||
})
|
||||
}, (error) => {
|
||||
bitmap.clear()
|
||||
reject(error)
|
||||
})
|
||||
// #endif
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 路径转base64
|
||||
* @param {Object} string
|
||||
*/
|
||||
export function pathToBase64(path) {
|
||||
if (/^data:/.test(path)) return path
|
||||
return new Promise((resolve, reject) => {
|
||||
// #ifdef H5
|
||||
let image = new Image();
|
||||
image.setAttribute("crossOrigin", 'Anonymous');
|
||||
image.onload = function() {
|
||||
let canvas = document.createElement('canvas');
|
||||
canvas.width = this.naturalWidth;
|
||||
canvas.height = this.naturalHeight;
|
||||
canvas.getContext('2d').drawImage(image, 0, 0);
|
||||
let result = canvas.toDataURL('image/png')
|
||||
resolve(result);
|
||||
canvas.height = canvas.width = 0
|
||||
}
|
||||
image.src = path + '?v=' + Math.random()
|
||||
image.onerror = (error) => {
|
||||
reject(error);
|
||||
};
|
||||
// #endif
|
||||
|
||||
// #ifdef MP
|
||||
if (uni.canIUse('getFileSystemManager')) {
|
||||
uni.getFileSystemManager().readFile({
|
||||
filePath: path,
|
||||
encoding: 'base64',
|
||||
success: (res) => {
|
||||
resolve('data:image/png;base64,' + res.data)
|
||||
},
|
||||
fail: (error) => {
|
||||
console.error({error, path})
|
||||
reject(error)
|
||||
}
|
||||
})
|
||||
}
|
||||
// #endif
|
||||
|
||||
// #ifdef APP-PLUS
|
||||
plus.io.resolveLocalFileSystemURL(getLocalFilePath(path), (entry) => {
|
||||
entry.file((file) => {
|
||||
const fileReader = new plus.io.FileReader()
|
||||
fileReader.onload = (data) => {
|
||||
resolve(data.target.result)
|
||||
}
|
||||
fileReader.onerror = (error) => {
|
||||
reject(error)
|
||||
}
|
||||
fileReader.readAsDataURL(file)
|
||||
}, reject)
|
||||
}, reject)
|
||||
// #endif
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
export function getImageInfo(path, useCORS) {
|
||||
const isCanvas2D = this && this.canvas && this.canvas.createImage
|
||||
return new Promise(async (resolve, reject) => {
|
||||
// let time = +new Date()
|
||||
let src = path.replace(/^@\//,'/')
|
||||
if (cache[path] && cache[path].errMsg) {
|
||||
resolve(cache[path])
|
||||
} else {
|
||||
try {
|
||||
// #ifdef MP || APP-PLUS
|
||||
if (isBase64(path) && (isCanvas2D ? isPC : true)) {
|
||||
src = await base64ToPath(path)
|
||||
}
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
if(useCORS) {
|
||||
src = await pathToBase64(path)
|
||||
}
|
||||
// #endif
|
||||
} catch (error) {
|
||||
reject({
|
||||
...error,
|
||||
src
|
||||
})
|
||||
}
|
||||
// #ifndef APP-NVUE
|
||||
if(isCanvas2D && !isPC) {
|
||||
const img = this.canvas.createImage()
|
||||
img.onload = function() {
|
||||
const image = {
|
||||
path: img,
|
||||
width: img.width,
|
||||
height: img.height
|
||||
}
|
||||
cache[path] = image
|
||||
resolve(cache[path])
|
||||
}
|
||||
img.onerror = function(err) {
|
||||
reject({err,path})
|
||||
}
|
||||
img.src = src
|
||||
return
|
||||
}
|
||||
// #endif
|
||||
uni.getImageInfo({
|
||||
src,
|
||||
success: (image) => {
|
||||
const localReg = /^\.|^\/(?=[^\/])/;
|
||||
// #ifdef MP-WEIXIN || MP-BAIDU || MP-QQ || MP-TOUTIAO
|
||||
image.path = localReg.test(src) ? `/${image.path}` : image.path;
|
||||
// #endif
|
||||
if(isCanvas2D) {
|
||||
const img = this.canvas.createImage()
|
||||
img.onload = function() {
|
||||
image.path = img
|
||||
cache[path] = image
|
||||
resolve(cache[path])
|
||||
}
|
||||
img.onerror = function(err) {
|
||||
reject({err,path})
|
||||
}
|
||||
img.src = src
|
||||
return
|
||||
}
|
||||
// #ifdef APP-PLUS
|
||||
// console.log('getImageInfo', +new Date() - time)
|
||||
// ios 比较严格 可能需要设置跨域
|
||||
if(uni.getSystemInfoSync().osName == 'ios' && useCORS) {
|
||||
pathToBase64(image.path).then(base64 => {
|
||||
image.path = base64
|
||||
cache[path] = image
|
||||
resolve(cache[path])
|
||||
}).catch(err => {
|
||||
console.error({err, path})
|
||||
reject({err,path})
|
||||
})
|
||||
return
|
||||
}
|
||||
// #endif
|
||||
cache[path] = image
|
||||
resolve(cache[path])
|
||||
},
|
||||
fail(err) {
|
||||
console.error({err, path})
|
||||
reject({err,path})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// #ifdef APP-PLUS
|
||||
const 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) {
|
||||
const localFilePath = plus.io.convertAbsoluteFileSystem(path)
|
||||
if (localFilePath !== path) {
|
||||
return localFilePath
|
||||
} else {
|
||||
path = path.substr(1)
|
||||
}
|
||||
}
|
||||
return '_www/' + path
|
||||
}
|
||||
// #endif
|
||||
|
||||
|
File diff suppressed because one or more lines are too long
119
uni_modules/lime-painter/hybrid/html/index.html
Normal file
119
uni_modules/lime-painter/hybrid/html/index.html
Normal file
@ -0,0 +1,119 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||
<title></title>
|
||||
<style type="text/css">
|
||||
html,
|
||||
body,
|
||||
canvas {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow-y: hidden;
|
||||
background-color: transparent;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<canvas id="lime-painter"></canvas>
|
||||
<script type="text/javascript" src="./uni.webview.1.5.3.js"></script>
|
||||
<script type="text/javascript" src="./painter.js"></script>
|
||||
<script>
|
||||
var cache = [];
|
||||
var painter = null;
|
||||
var canvas = null;
|
||||
var context = null;
|
||||
var timer = null;
|
||||
var pixelRatio = 1;
|
||||
console.log = function (...args) {
|
||||
postMessage(args);
|
||||
};
|
||||
// function stringify(key, value) {
|
||||
// if (typeof value === 'object' && value !== null) {
|
||||
// if (cache.indexOf(value) !== -1) {
|
||||
// return;
|
||||
// }
|
||||
// cache.push(value);
|
||||
// }
|
||||
// return value;
|
||||
// };
|
||||
|
||||
function emit(event, data) {
|
||||
postMessage({
|
||||
event,
|
||||
data: (typeof data !== 'object' && data !== null ? data : JSON.stringify(data))
|
||||
});
|
||||
cache = [];
|
||||
};
|
||||
function postMessage(data) {
|
||||
uni.postMessage({
|
||||
data
|
||||
});
|
||||
};
|
||||
|
||||
function init(dpr) {
|
||||
canvas = document.querySelector('#lime-painter');
|
||||
context = canvas.getContext('2d');
|
||||
pixelRatio = dpr || window.devicePixelRatio;
|
||||
painter = new Painter({
|
||||
id: 'lime-painter',
|
||||
context,
|
||||
canvas,
|
||||
pixelRatio,
|
||||
width: canvas.offsetWidth,
|
||||
height: canvas.offsetHeight,
|
||||
listen: {
|
||||
onProgress(v) {
|
||||
emit('progressChange', v);
|
||||
},
|
||||
onEffectFail(err) {
|
||||
//console.error(err)
|
||||
emit('fail', err);
|
||||
}
|
||||
}
|
||||
});
|
||||
emit('inited', true);
|
||||
};
|
||||
function save(args) {
|
||||
delete args.success;
|
||||
delete args.fail;
|
||||
clearTimeout(timer);
|
||||
timer = setTimeout(() => {
|
||||
const path = painter.save(args);
|
||||
if (typeof path == 'string') {
|
||||
const index = Math.ceil(path.length / 8);
|
||||
for (var i = 0; i < 8; i++) {
|
||||
if (i == 7) {
|
||||
emit('success', path.substr(i * index, index));
|
||||
} else {
|
||||
emit('file', path.substr(i * index, index));
|
||||
}
|
||||
};
|
||||
} else {
|
||||
// console.log('canvas no data')
|
||||
emit('fail', 'canvas no data');
|
||||
};
|
||||
}, 30);
|
||||
};
|
||||
async function source(args) {
|
||||
let size = await painter.source(args);
|
||||
emit('layoutChange', size);
|
||||
if(!canvas.height) {
|
||||
console.log('canvas no size')
|
||||
emit('fail', 'canvas no size');
|
||||
}
|
||||
painter.render().catch(err => {
|
||||
// console.error(err)
|
||||
emit('fail', err);
|
||||
});
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
1
uni_modules/lime-painter/hybrid/html/painter.js
Normal file
1
uni_modules/lime-painter/hybrid/html/painter.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
93
uni_modules/lime-painter/package.json
Normal file
93
uni_modules/lime-painter/package.json
Normal file
@ -0,0 +1,93 @@
|
||||
{
|
||||
"id": "lime-painter",
|
||||
"displayName": "海报画板",
|
||||
"version": "1.9.6.6",
|
||||
"description": "一款canvas海报组件,更优雅的海报生成方案,有限的支持富文本",
|
||||
"keywords": [
|
||||
"海报",
|
||||
"富文本",
|
||||
"生成海报",
|
||||
"生成二维码",
|
||||
"JSON"
|
||||
],
|
||||
"repository": "https://gitee.com/liangei/lime-painter",
|
||||
"engines": {
|
||||
"HBuilderX": "^3.4.14"
|
||||
},
|
||||
"dcloudext": {
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": "305716444"
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "无",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": "",
|
||||
"type": "component-vue"
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y",
|
||||
"alipay": "n"
|
||||
},
|
||||
"client": {
|
||||
"App": {
|
||||
"app-vue": "y",
|
||||
"app-nvue": "y"
|
||||
},
|
||||
"H5-mobile": {
|
||||
"Safari": "y",
|
||||
"Android Browser": "y",
|
||||
"微信浏览器(Android)": "y",
|
||||
"QQ浏览器(Android)": "y"
|
||||
},
|
||||
"H5-pc": {
|
||||
"Chrome": "y",
|
||||
"IE": "u",
|
||||
"Edge": "u",
|
||||
"Firefox": "u",
|
||||
"Safari": "y"
|
||||
},
|
||||
"小程序": {
|
||||
"微信": "y",
|
||||
"阿里": "y",
|
||||
"百度": "y",
|
||||
"字节跳动": "y",
|
||||
"QQ": "y",
|
||||
"钉钉": "u",
|
||||
"快手": "u",
|
||||
"飞书": "u",
|
||||
"京东": "u"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
},
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"name": "lime-painter",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC"
|
||||
}
|
388
uni_modules/lime-painter/parser.js
Normal file
388
uni_modules/lime-painter/parser.js
Normal file
@ -0,0 +1,388 @@
|
||||
/*
|
||||
* HTML5 Parser By Sam Blowes
|
||||
*
|
||||
* Designed for HTML5 documents
|
||||
*
|
||||
* Original code by John Resig (ejohn.org)
|
||||
* http://ejohn.org/blog/pure-javascript-html-parser/
|
||||
* Original code by Erik Arvidsson, Mozilla Public License
|
||||
* http://erik.eae.net/simplehtmlparser/simplehtmlparser.js
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
* License
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* This code is triple licensed using Apache Software License 2.0,
|
||||
* Mozilla Public License or GNU Public License
|
||||
*
|
||||
* ////////////////////////////////////////////////////////////////////////////
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy
|
||||
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* ////////////////////////////////////////////////////////////////////////////
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS"
|
||||
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing rights and limitations
|
||||
* under the License.
|
||||
*
|
||||
* The Original Code is Simple HTML Parser.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Erik Arvidsson.
|
||||
* Portions created by Erik Arvidssson are Copyright (C) 2004. All Rights
|
||||
* Reserved.
|
||||
*
|
||||
* ////////////////////////////////////////////////////////////////////////////
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
* Usage
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* // Use like so:
|
||||
* HTMLParser(htmlString, {
|
||||
* start: function(tag, attrs, unary) {},
|
||||
* end: function(tag) {},
|
||||
* chars: function(text) {},
|
||||
* comment: function(text) {}
|
||||
* });
|
||||
*
|
||||
* // or to get an XML string:
|
||||
* HTMLtoXML(htmlString);
|
||||
*
|
||||
* // or to get an XML DOM Document
|
||||
* HTMLtoDOM(htmlString);
|
||||
*
|
||||
* // or to inject into an existing document/DOM node
|
||||
* HTMLtoDOM(htmlString, document);
|
||||
* HTMLtoDOM(htmlString, document.body);
|
||||
*
|
||||
*/
|
||||
// Regular Expressions for parsing tags and attributes
|
||||
var startTag = /^<([-A-Za-z0-9_]+)((?:\s+[a-zA-Z_:][-a-zA-Z0-9_:.]*(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)>/;
|
||||
var endTag = /^<\/([-A-Za-z0-9_]+)[^>]*>/;
|
||||
var attr = /([a-zA-Z_:][-a-zA-Z0-9_:.]*)(?:\s*=\s*(?:(?:"((?:\\.|[^"])*)")|(?:'((?:\\.|[^'])*)')|([^>\s]+)))?/g; // Empty Elements - HTML 5
|
||||
|
||||
var empty = makeMap('area,base,basefont,br,col,frame,hr,img,input,link,meta,param,embed,command,keygen,source,track,wbr'); // Block Elements - HTML 5
|
||||
// fixed by xxx 将 ins 标签从块级名单中移除
|
||||
|
||||
var block = makeMap('a,address,article,applet,aside,audio,blockquote,button,canvas,center,dd,del,dir,div,dl,dt,fieldset,figcaption,figure,footer,form,frameset,h1,h2,h3,h4,h5,h6,header,hgroup,hr,iframe,isindex,li,map,menu,noframes,noscript,object,ol,output,p,pre,section,script,table,tbody,td,tfoot,th,thead,tr,ul,video'); // Inline Elements - HTML 5
|
||||
|
||||
var inline = makeMap('abbr,acronym,applet,b,basefont,bdo,big,br,button,cite,code,del,dfn,em,font,i,iframe,img,input,ins,kbd,label,map,object,q,s,samp,script,select,small,span,strike,strong,sub,sup,textarea,tt,u,var'); // Elements that you can, intentionally, leave open
|
||||
// (and which close themselves)
|
||||
|
||||
var closeSelf = makeMap('colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr'); // Attributes that have their values filled in disabled="disabled"
|
||||
|
||||
var fillAttrs = makeMap('checked,compact,declare,defer,disabled,ismap,multiple,nohref,noresize,noshade,nowrap,readonly,selected'); // Special Elements (can contain anything)
|
||||
|
||||
var special = makeMap('script,style');
|
||||
function HTMLParser(html, handler) {
|
||||
var index;
|
||||
var chars;
|
||||
var match;
|
||||
var stack = [];
|
||||
var last = html;
|
||||
|
||||
stack.last = function () {
|
||||
return this[this.length - 1];
|
||||
};
|
||||
|
||||
while (html) {
|
||||
chars = true; // Make sure we're not in a script or style element
|
||||
|
||||
if (!stack.last() || !special[stack.last()]) {
|
||||
// Comment
|
||||
if (html.indexOf('<!--') == 0) {
|
||||
index = html.indexOf('-->');
|
||||
|
||||
if (index >= 0) {
|
||||
if (handler.comment) {
|
||||
handler.comment(html.substring(4, index));
|
||||
}
|
||||
|
||||
html = html.substring(index + 3);
|
||||
chars = false;
|
||||
} // end tag
|
||||
|
||||
} else if (html.indexOf('</') == 0) {
|
||||
match = html.match(endTag);
|
||||
|
||||
if (match) {
|
||||
html = html.substring(match[0].length);
|
||||
match[0].replace(endTag, parseEndTag);
|
||||
chars = false;
|
||||
} // start tag
|
||||
|
||||
} else if (html.indexOf('<') == 0) {
|
||||
match = html.match(startTag);
|
||||
|
||||
if (match) {
|
||||
html = html.substring(match[0].length);
|
||||
match[0].replace(startTag, parseStartTag);
|
||||
chars = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (chars) {
|
||||
index = html.indexOf('<');
|
||||
var text = index < 0 ? html : html.substring(0, index);
|
||||
html = index < 0 ? '' : html.substring(index);
|
||||
|
||||
if (handler.chars) {
|
||||
handler.chars(text);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
html = html.replace(new RegExp('([\\s\\S]*?)<\/' + stack.last() + '[^>]*>'), function (all, text) {
|
||||
text = text.replace(/<!--([\s\S]*?)-->|<!\[CDATA\[([\s\S]*?)]]>/g, '$1$2');
|
||||
|
||||
if (handler.chars) {
|
||||
handler.chars(text);
|
||||
}
|
||||
|
||||
return '';
|
||||
});
|
||||
parseEndTag('', stack.last());
|
||||
}
|
||||
|
||||
if (html == last) {
|
||||
throw 'Parse Error: ' + html;
|
||||
}
|
||||
|
||||
last = html;
|
||||
} // Clean up any remaining tags
|
||||
|
||||
|
||||
parseEndTag();
|
||||
|
||||
function parseStartTag(tag, tagName, rest, unary) {
|
||||
tagName = tagName.toLowerCase();
|
||||
if (block[tagName]) {
|
||||
while (stack.last() && inline[stack.last()]) {
|
||||
parseEndTag('', stack.last());
|
||||
}
|
||||
}
|
||||
|
||||
if (closeSelf[tagName] && stack.last() == tagName) {
|
||||
parseEndTag('', tagName);
|
||||
}
|
||||
|
||||
unary = empty[tagName] || !!unary;
|
||||
|
||||
if (!unary) {
|
||||
stack.push(tagName);
|
||||
}
|
||||
|
||||
if (handler.start) {
|
||||
var attrs = [];
|
||||
rest.replace(attr, function (match, name) {
|
||||
var value = arguments[2] ? arguments[2] : arguments[3] ? arguments[3] : arguments[4] ? arguments[4] : fillAttrs[name] ? name : '';
|
||||
attrs.push({
|
||||
name: name,
|
||||
value: value,
|
||||
escaped: value.replace(/(^|[^\\])"/g, '$1\\\"') // "
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
if (handler.start) {
|
||||
handler.start(tagName, attrs, unary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function parseEndTag(tag, tagName) {
|
||||
// If no tag name is provided, clean shop
|
||||
if (!tagName) {
|
||||
var pos = 0;
|
||||
} // Find the closest opened tag of the same type
|
||||
else {
|
||||
for (var pos = stack.length - 1; pos >= 0; pos--) {
|
||||
if (stack[pos] == tagName) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pos >= 0) {
|
||||
// Close all the open elements, up the stack
|
||||
for (var i = stack.length - 1; i >= pos; i--) {
|
||||
if (handler.end) {
|
||||
handler.end(stack[i]);
|
||||
}
|
||||
} // Remove the open elements from the stack
|
||||
|
||||
|
||||
stack.length = pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function makeMap(str) {
|
||||
var obj = {};
|
||||
var items = str.split(',');
|
||||
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
obj[items[i]] = true;
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
function removeDOCTYPE(html) {
|
||||
return html.replace(/<\?xml.*\?>\n/, '').replace(/<!doctype.*>\n/, '').replace(/<!DOCTYPE.*>\n/, '');
|
||||
}
|
||||
|
||||
function parseAttrs(attrs) {
|
||||
return attrs.reduce(function (pre, attr) {
|
||||
var value = attr.value;
|
||||
var name = attr.name;
|
||||
if (pre[name]) {
|
||||
pre[name] = pre[name] + " " + value;
|
||||
} else {
|
||||
pre[name] = value;
|
||||
}
|
||||
|
||||
return pre;
|
||||
}, {});
|
||||
}
|
||||
function convertStyleStringToJSON(styleString) {
|
||||
var styles = styleString.split(";"); // 通过分号将样式字符串分割为多个样式声明
|
||||
var result = {};
|
||||
|
||||
styles.forEach(function(style) {
|
||||
var styleParts = style.split(":"); // 通过冒号将样式声明分割为属性和值
|
||||
var property = styleParts[0].trim();
|
||||
var value = styleParts[1] && styleParts[1].trim();
|
||||
|
||||
if (property && value) {
|
||||
result[property] = value; // 将属性和值添加到结果对象中
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
function parseHtml(html) {
|
||||
html = removeDOCTYPE(html);
|
||||
var stacks = [];
|
||||
var results = {
|
||||
node: 'root',
|
||||
children: []
|
||||
};
|
||||
HTMLParser(html, {
|
||||
start: function start(tag, attrs, unary) {
|
||||
var node = {
|
||||
name: tag
|
||||
};
|
||||
|
||||
if (attrs.length !== 0) {
|
||||
node.attrs = parseAttrs(attrs);
|
||||
node.styles = node.attrs.style ? convertStyleStringToJSON(node.attrs.style) : {}
|
||||
}
|
||||
|
||||
if(!node.type) {
|
||||
if(inline[node.name] && node.name !== 'img' ) {
|
||||
node.type = 'text';
|
||||
if(node.name == 'br') {
|
||||
node.text = '\n'
|
||||
} else if(node.name == 'strong'){
|
||||
node.styles.fontWeight = 'bold'
|
||||
}
|
||||
} else if(node.name == 'img'){
|
||||
node.type = 'image'
|
||||
node.src = node.attrs.src
|
||||
} else {
|
||||
node.type = 'view'
|
||||
if(['h1','h2','h3','h4','h5','h6'].includes(node.name)) {
|
||||
node.styles.fontWeight = 'bold'
|
||||
}
|
||||
}
|
||||
}
|
||||
if (unary) {
|
||||
var parent = stacks[0] || results;
|
||||
|
||||
if (!parent.children) {
|
||||
parent.children = [];
|
||||
}
|
||||
|
||||
parent.children.push(node);
|
||||
} else {
|
||||
stacks.unshift(node);
|
||||
}
|
||||
},
|
||||
end: function end(tag) {
|
||||
var node = stacks.shift();
|
||||
if (node.name !== tag) console.error('invalid state: mismatch end tag');
|
||||
if (stacks.length === 0) {
|
||||
results.children.push(node);
|
||||
} else {
|
||||
var parent = stacks[0];
|
||||
|
||||
if (!parent.children) {
|
||||
parent.children = [];
|
||||
}
|
||||
parent.children.push(node);
|
||||
}
|
||||
const isTextBox = node.children && node.children.length > 1 && node.children.every(child => {
|
||||
return ['text','image'].includes(child.type)
|
||||
})
|
||||
if(isTextBox) {
|
||||
node.type = 'textBox'
|
||||
}
|
||||
},
|
||||
chars: function chars(text) {
|
||||
var node = {
|
||||
type: 'text',
|
||||
text: text
|
||||
};
|
||||
|
||||
if (stacks.length === 0) {
|
||||
results.children.push(node);
|
||||
} else {
|
||||
var parent = stacks[0];
|
||||
|
||||
if (!parent.children) {
|
||||
parent.children = [];
|
||||
}
|
||||
|
||||
parent.children.push(node);
|
||||
}
|
||||
},
|
||||
comment: function comment(text) {
|
||||
var node = {
|
||||
node: 'comment',
|
||||
text: text
|
||||
};
|
||||
var parent = stacks[0];
|
||||
|
||||
if (!parent.children) {
|
||||
parent.children = [];
|
||||
}
|
||||
|
||||
parent.children.push(node);
|
||||
}
|
||||
});
|
||||
return results.children;
|
||||
}
|
||||
|
||||
export default parseHtml;
|
961
uni_modules/lime-painter/readme.md
Normal file
961
uni_modules/lime-painter/readme.md
Normal file
@ -0,0 +1,961 @@
|
||||
# Painter 画板 测试版
|
||||
|
||||
> uniapp 海报画板,更优雅的海报生成方案
|
||||
> [查看更多](https://limeui.qcoon.cn/#/painter)
|
||||
|
||||
## 平台兼容
|
||||
|
||||
| H5 | 微信小程序 | 支付宝小程序 | 百度小程序 | 头条小程序 | QQ 小程序 | App |
|
||||
| --- | ---------- | ------------ | ---------- | ---------- | --------- | --- |
|
||||
| √ | √ | √ | 未测 | √ | √ | √ |
|
||||
|
||||
## 安装
|
||||
在市场导入**[海报画板](https://ext.dcloud.net.cn/plugin?id=2389)uni_modules**版本的即可,无需`import`
|
||||
|
||||
## 代码演示
|
||||
|
||||
### 插件demo
|
||||
- lime-painter 为 demo
|
||||
- 位于 uni_modules/lime-painter/components/lime-painter
|
||||
- 导入插件后直接使用可查看demo
|
||||
```vue
|
||||
<lime-painter />
|
||||
```
|
||||
|
||||
|
||||
### 基本用法
|
||||
|
||||
- 插件提供 JSON 及 Template 的方式绘制海报
|
||||
- 参考 css 块状流布局模拟 css schema。
|
||||
- 另外flex布局还不是成完善,请谨慎使用,普通的流布局我觉得已经够用了。
|
||||
|
||||
#### 方式一 Template
|
||||
|
||||
- 提供`l-painter-view`、`l-painter-text`、`l-painter-image`、`l-painter-qrcode`四种类型组件
|
||||
- 通过 `css` 属性绘制样式,与 style 使用方式保持一致。
|
||||
```html
|
||||
<l-painter>
|
||||
//如果使用Template出现顺序错乱,可使用`template` 等所有变量完成再显示
|
||||
<template v-if="show">
|
||||
<l-painter-view
|
||||
css="background: #07c160; height: 120rpx; width: 120rpx; display: inline-block"
|
||||
></l-painter-view>
|
||||
<l-painter-view
|
||||
css="background: #1989fa; height: 120rpx; width: 120rpx; border-top-right-radius: 60rpx; border-bottom-left-radius: 60rpx; display: inline-block; margin: 0 30rpx;"
|
||||
></l-painter-view>
|
||||
<l-painter-view
|
||||
css="background: #ff9d00; height: 120rpx; width: 120rpx; border-radius: 50%; display: inline-block"
|
||||
></l-painter-view>
|
||||
<template>
|
||||
</l-painter>
|
||||
```
|
||||
|
||||
#### 方式二 JSON
|
||||
|
||||
- 在 json 里四种类型组件的`type`为`view`、`text`、`image`、`qrcode`
|
||||
- 通过 `board` 设置海报所需的 JSON 数据进行绘制或`ref`获取组件实例调用组件内的`render(json)`
|
||||
- 所有类型的 schema 都具有`css`字段,css 的 key 值使用**驼峰**如:`lineHeight`
|
||||
|
||||
```html
|
||||
<l-painter :board="poster"/>
|
||||
```
|
||||
|
||||
```js
|
||||
data() {
|
||||
return {
|
||||
poster: {
|
||||
css: {
|
||||
// 根节点若无尺寸,自动获取父级节点
|
||||
width: '750rpx'
|
||||
},
|
||||
views: [
|
||||
{
|
||||
css: {
|
||||
background: "#07c160",
|
||||
height: "120rpx",
|
||||
width: "120rpx",
|
||||
display: "inline-block"
|
||||
},
|
||||
type: "view"
|
||||
},
|
||||
{
|
||||
css: {
|
||||
background: "#1989fa",
|
||||
height: "120rpx",
|
||||
width: "120rpx",
|
||||
borderTopRightRadius: "60rpx",
|
||||
borderBottomLeftRadius: "60rpx",
|
||||
display: "inline-block",
|
||||
margin: "0 30rpx"
|
||||
},
|
||||
views: [],
|
||||
type: "view"
|
||||
},
|
||||
{
|
||||
css: {
|
||||
background: "#ff9d00",
|
||||
height: "120rpx",
|
||||
width: "120rpx",
|
||||
borderRadius: "50%",
|
||||
display: "inline-block"
|
||||
},
|
||||
views: [],
|
||||
type: "view"
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### View 容器
|
||||
|
||||
- 类似于 `div` 可以嵌套承载更多的 view、text、image,qrcode 共同构建一颗完整的节点树
|
||||
- 在 JSON 里具有 `views` 的数组字段,用于嵌套承载节点。
|
||||
|
||||
#### 方式一 Template
|
||||
|
||||
```html
|
||||
<l-painter>
|
||||
<l-painter-view css="background: #f0f0f0; padding-top: 100rpx;">
|
||||
<l-painter-view
|
||||
css="background: #d9d9d9; width: 33.33%; height: 100rpx; display: inline-block"
|
||||
></l-painter-view>
|
||||
<l-painter-view
|
||||
css="background: #bfbfbf; width: 66.66%; height: 100rpx; display: inline-block"
|
||||
></l-painter-view>
|
||||
</l-painter-view>
|
||||
</l-painter>
|
||||
```
|
||||
|
||||
#### 方式二 JSON
|
||||
|
||||
```js
|
||||
{
|
||||
css: {},
|
||||
views: [
|
||||
{
|
||||
type: 'view',
|
||||
css: {
|
||||
background: '#f0f0f0',
|
||||
paddingTop: '100rpx'
|
||||
},
|
||||
views: [
|
||||
{
|
||||
type: 'view',
|
||||
css: {
|
||||
background: '#d9d9d9',
|
||||
width: '33.33%',
|
||||
height: '100rpx',
|
||||
display: 'inline-block'
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'view',
|
||||
css: {
|
||||
background: '#bfbfbf',
|
||||
width: '66.66%',
|
||||
height: '100rpx',
|
||||
display: 'inline-block'
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Text 文本
|
||||
|
||||
- 通过 `text` 属性填写文本内容。
|
||||
- 支持`\n`换行符
|
||||
- 支持省略号,使用 css 的`line-clamp`设置行数,当文字内容超过会显示省略号。
|
||||
- 支持`text-decoration`
|
||||
|
||||
#### 方式一 Template
|
||||
|
||||
```html
|
||||
<l-painter>
|
||||
<l-painter-view css="background: #e0e2db; padding: 30rpx; color: #222a29">
|
||||
<l-painter-text
|
||||
text="登鹳雀楼\n白日依山尽,黄河入海流\n欲穷千里目,更上一层楼"
|
||||
/>
|
||||
<l-painter-text
|
||||
text="登鹳雀楼\n白日依山尽,黄河入海流\n欲穷千里目,更上一层楼"
|
||||
css="text-align:center; padding-top: 20rpx; text-decoration: line-through "
|
||||
/>
|
||||
<l-painter-text
|
||||
text="登鹳雀楼\n白日依山尽,黄河入海流\n欲穷千里目,更上一层楼"
|
||||
css="text-align:right; padding-top: 20rpx"
|
||||
/>
|
||||
<l-painter-text
|
||||
text="水调歌头\n明月几时有?把酒问青天。不知天上宫阙,今夕是何年。我欲乘风归去,又恐琼楼玉宇,高处不胜寒。起舞弄清影,何似在人间。"
|
||||
css="line-clamp: 3; padding-top: 20rpx; background: linear-gradient(,#ff971b 0%, #ff5000 100%); background-clip: text"
|
||||
/>
|
||||
</l-painter-view>
|
||||
</l-painter>
|
||||
```
|
||||
|
||||
#### 方式二 JSON
|
||||
|
||||
```js
|
||||
// 基础用法
|
||||
{
|
||||
type: 'text',
|
||||
text: '登鹳雀楼\n白日依山尽,黄河入海流\n欲穷千里目,更上一层楼',
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
text: '登鹳雀楼\n白日依山尽,黄河入海流\n欲穷千里目,更上一层楼',
|
||||
css: {
|
||||
// 设置居中对齐
|
||||
textAlign: 'center',
|
||||
// 设置中划线
|
||||
textDecoration: 'line-through'
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
text: '登鹳雀楼\n白日依山尽,黄河入海流\n欲穷千里目,更上一层楼',
|
||||
css: {
|
||||
// 设置右对齐
|
||||
textAlign: 'right',
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
text: '登鹳雀楼\n白日依山尽,黄河入海流\n欲穷千里目,更上一层楼',
|
||||
css: {
|
||||
// 设置行数,超出显示省略号
|
||||
lineClamp: 3,
|
||||
// 渐变文字
|
||||
background: 'linear-gradient(,#ff971b 0%, #1989fa 100%)',
|
||||
backgroundClip: 'text'
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Image 图片
|
||||
|
||||
- 通过 `src` 属性填写图片路径。
|
||||
- 图片路径支持:网络图片,本地 static 里的图片路径,缓存路径,**字节的static目录是写相对路径**
|
||||
- 通过 `css` 的 `object-fit`属性可以设置图片的填充方式,可选值见下方 CSS 表格。
|
||||
- 通过 `css` 的 `object-position`配合 `object-fit` 可以设置图片的对齐方式,类似于`background-position`,详情见下方 CSS 表格。
|
||||
- 使用网络图片时:小程序需要去公众平台配置 [downloadFile](https://mp.weixin.qq.com/) 域名
|
||||
- 使用网络图片时:**H5 和 Nvue 需要决跨域问题**
|
||||
|
||||
#### 方式一 Template
|
||||
|
||||
```html
|
||||
<l-painter>
|
||||
<!-- 基础用法 -->
|
||||
<l-painter-image
|
||||
src="https://m.360buyimg.com/babel/jfs/t1/196317/32/13733/288158/60f4ea39E6fb378ed/d69205b1a8ed3c97.jpg"
|
||||
css="width: 200rpx; height: 200rpx"
|
||||
/>
|
||||
<!-- 填充方式 -->
|
||||
<!-- css object-fit 设置 填充方式 见下方表格-->
|
||||
<l-painter-image
|
||||
src="https://m.360buyimg.com/babel/jfs/t1/196317/32/13733/288158/60f4ea39E6fb378ed/d69205b1a8ed3c97.jpg"
|
||||
css="width: 200rpx; height: 200rpx; object-fit: contain; background: #eee"
|
||||
/>
|
||||
<!-- css object-position 设置 图片的对齐方式-->
|
||||
<l-painter-image
|
||||
src="https://m.360buyimg.com/babel/jfs/t1/196317/32/13733/288158/60f4ea39E6fb378ed/d69205b1a8ed3c97.jpg"
|
||||
css="width: 200rpx; height: 200rpx; object-fit: contain; object-position: 50% 50%; background: #eee"
|
||||
/>
|
||||
</l-painter>
|
||||
```
|
||||
|
||||
#### 方式二 JSON
|
||||
|
||||
```js
|
||||
// 基础用法
|
||||
{
|
||||
type: 'image',
|
||||
src: 'https://m.360buyimg.com/babel/jfs/t1/196317/32/13733/288158/60f4ea39E6fb378ed/d69205b1a8ed3c97.jpg',
|
||||
css: {
|
||||
width: '200rpx',
|
||||
height: '200rpx'
|
||||
}
|
||||
},
|
||||
// 填充方式
|
||||
// css objectFit 设置 填充方式 见下方表格
|
||||
{
|
||||
type: 'image',
|
||||
src: 'https://m.360buyimg.com/babel/jfs/t1/196317/32/13733/288158/60f4ea39E6fb378ed/d69205b1a8ed3c97.jpg',
|
||||
css: {
|
||||
width: '200rpx',
|
||||
height: '200rpx',
|
||||
objectFit: 'contain'
|
||||
}
|
||||
},
|
||||
// css objectPosition 设置 图片的对齐方式
|
||||
{
|
||||
type: 'image',
|
||||
src: 'https://m.360buyimg.com/babel/jfs/t1/196317/32/13733/288158/60f4ea39E6fb378ed/d69205b1a8ed3c97.jpg',
|
||||
css: {
|
||||
width: '200rpx',
|
||||
height: '200rpx',
|
||||
objectFit: 'contain',
|
||||
objectPosition: '50% 50%'
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Qrcode 二维码
|
||||
|
||||
- 通过`text`属性填写需要生成二维码的文本。
|
||||
- 通过 `css` 里的 `color` 可设置生成码点的颜色。
|
||||
- 通过 `css` 里的 `background`可设置背景色。
|
||||
- 通过 `css `里的 `width`、`height`设置尺寸。
|
||||
|
||||
#### 方式一 Template
|
||||
|
||||
```html
|
||||
<l-painter>
|
||||
<l-painter-qrcode
|
||||
text="limeui.qcoon.cn"
|
||||
css="width: 200rpx; height: 200rpx"
|
||||
/>
|
||||
</l-painter>
|
||||
```
|
||||
|
||||
#### 方式二 JSON
|
||||
|
||||
```js
|
||||
{
|
||||
type: 'qrcode',
|
||||
text: 'limeui.qcoon.cn',
|
||||
css: {
|
||||
width: '200rpx',
|
||||
height: '200rpx',
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 富文本
|
||||
- 这是一个有限支持的测试能力,只能通过JSON方式,不要抱太大希望!
|
||||
- 首先需要把富文本转成JSON,这需要引入`parser`这个包,如果你不使用是不会进入主包
|
||||
|
||||
```html
|
||||
<l-painter ref="painter"/>
|
||||
```
|
||||
```js
|
||||
import parseHtml from '@/uni_modules/lime-painter/parser'
|
||||
const json = parseHtml(`<p><span>测试测试</span><img src="/static/logo.png"/></p>`)
|
||||
this.$refs.painter.render(json)
|
||||
```
|
||||
|
||||
### 生成图片
|
||||
|
||||
- 方式1、通过设置`isCanvasToTempFilePath`自动生成图片并在 `@success` 事件里接收海报临时路径
|
||||
- 方式2、通过调用内部方法生成图片:
|
||||
|
||||
```html
|
||||
<l-painter ref="painter">...code</l-painter>
|
||||
```
|
||||
|
||||
```js
|
||||
this.$refs.painter.canvasToTempFilePathSync({
|
||||
fileType: "jpg",
|
||||
// 如果返回的是base64是无法使用 saveImageToPhotosAlbum,需要设置 pathType为url
|
||||
pathType: 'url',
|
||||
quality: 1,
|
||||
success: (res) => {
|
||||
console.log(res.tempFilePath);
|
||||
// 非H5 保存到相册
|
||||
// H5 提示用户长按图另存
|
||||
uni.saveImageToPhotosAlbum({
|
||||
filePath: res.tempFilePath,
|
||||
success: function () {
|
||||
console.log('save success');
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
### 主动调用方式
|
||||
|
||||
- 通过获取组件实例内部的`render`函数 传递`JSON`即可
|
||||
|
||||
```html
|
||||
<l-painter ref="painter" />
|
||||
```
|
||||
|
||||
```js
|
||||
// 渲染
|
||||
this.$refs.painter.render(jsonSchema);
|
||||
// 生成图片
|
||||
this.$refs.painter.canvasToTempFilePathSync({
|
||||
fileType: "jpg",
|
||||
// 如果返回的是base64是无法使用 saveImageToPhotosAlbum,需要设置 pathType为url
|
||||
pathType: 'url',
|
||||
quality: 1,
|
||||
success: (res) => {
|
||||
console.log(res.tempFilePath);
|
||||
// 非H5 保存到相册
|
||||
uni.saveImageToPhotosAlbum({
|
||||
filePath: res.tempFilePath,
|
||||
success: function () {
|
||||
console.log('save success');
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
### H5跨域
|
||||
- 一般是需要后端或管理OSS资源的大佬处理
|
||||
- 一般OSS的处理方式:
|
||||
|
||||
1、设置来源
|
||||
```cmd
|
||||
*
|
||||
```
|
||||
|
||||
2、允许Methods
|
||||
```html
|
||||
GET
|
||||
```
|
||||
|
||||
3、允许Headers
|
||||
```html
|
||||
access-control-allow-origin:*
|
||||
```
|
||||
|
||||
4、最后如果还是不行,可试下给插件设置`useCORS`
|
||||
```html
|
||||
<l-painter useCORS>
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 海报示例
|
||||
|
||||
- 提供一份示例,只把插件当成生成图片的工具,非必要不要在弹窗里使用。
|
||||
- 通过设置`isCanvasToTempFilePath`主动生成图片,再由 `@success` 事件接收海报临时路径
|
||||
- 设置`hidden`隐藏画板。
|
||||
请注意,示例用到了图片,海报的渲染是包括下载图片的时间,也许在某天图片会失效或访问超级慢,请更换为你的图片再查看,另外如果你是小程序请在使用示例时把**不校验合法域名**勾上!!!!!不然不显示还以为是插件的锅,求求了大佬们!
|
||||
#### 方式一 Template
|
||||
|
||||
```html
|
||||
<image :src="path" mode="widthFix"></image>
|
||||
<l-painter
|
||||
isCanvasToTempFilePath
|
||||
@success="path = $event"
|
||||
hidden
|
||||
css="width: 750rpx; padding-bottom: 40rpx; background: linear-gradient(,#ff971b 0%, #ff5000 100%)"
|
||||
>
|
||||
<l-painter-image
|
||||
src="https://m.360buyimg.com/babel/jfs/t1/196317/32/13733/288158/60f4ea39E6fb378ed/d69205b1a8ed3c97.jpg"
|
||||
css="margin-left: 40rpx; margin-top: 40rpx; width: 84rpx; height: 84rpx; border-radius: 50%;"
|
||||
/>
|
||||
<l-painter-view
|
||||
css="margin-top: 40rpx; padding-left: 20rpx; display: inline-block"
|
||||
>
|
||||
<l-painter-text
|
||||
text="隔壁老王"
|
||||
css="display: block; padding-bottom: 10rpx; color: #fff; font-size: 32rpx; fontWeight: bold"
|
||||
/>
|
||||
<l-painter-text
|
||||
text="为您挑选了一个好物"
|
||||
css="color: rgba(255,255,255,.7); font-size: 24rpx"
|
||||
/>
|
||||
</l-painter-view>
|
||||
<l-painter-view
|
||||
css="margin-left: 40rpx; margin-top: 30rpx; padding: 32rpx; box-sizing: border-box; background: #fff; border-radius: 16rpx; width: 670rpx; box-shadow: 0 20rpx 58rpx rgba(0,0,0,.15)"
|
||||
>
|
||||
<l-painter-image
|
||||
src="https://m.360buyimg.com/babel/jfs/t1/196317/32/13733/288158/60f4ea39E6fb378ed/d69205b1a8ed3c97.jpg"
|
||||
css="object-fit: cover; object-position: 50% 50%; width: 606rpx; height: 606rpx; border-radius: 12rpx;"
|
||||
/>
|
||||
<l-painter-view
|
||||
css="margin-top: 32rpx; color: #FF0000; font-weight: bold; font-size: 28rpx; line-height: 1em;"
|
||||
>
|
||||
<l-painter-text text="¥" css="vertical-align: bottom" />
|
||||
<l-painter-text
|
||||
text="39"
|
||||
css="vertical-align: bottom; font-size: 58rpx"
|
||||
/>
|
||||
<l-painter-text text=".39" css="vertical-align: bottom" />
|
||||
<l-painter-text
|
||||
text="¥59.99"
|
||||
css="vertical-align: bottom; padding-left: 10rpx; font-weight: normal; text-decoration: line-through; color: #999999"
|
||||
/>
|
||||
</l-painter-view>
|
||||
<l-painter-view css="margin-top: 32rpx; font-size: 26rpx; color: #8c5400">
|
||||
<l-painter-text text="自营" css="color: #212121; background: #ffb400;" />
|
||||
<l-painter-text
|
||||
text="30天最低价"
|
||||
css="margin-left: 16rpx; background: #fff4d9; text-decoration: line-through;"
|
||||
/>
|
||||
<l-painter-text
|
||||
text="满减优惠"
|
||||
css="margin-left: 16rpx; background: #fff4d9"
|
||||
/>
|
||||
<l-painter-text
|
||||
text="超高好评"
|
||||
css="margin-left: 16rpx; background: #fff4d9"
|
||||
/>
|
||||
</l-painter-view>
|
||||
<l-painter-view css="margin-top: 30rpx">
|
||||
<l-painter-text
|
||||
css="line-clamp: 2; color: #333333; line-height: 1.8em; font-size: 36rpx; width: 478rpx; padding-right:32rpx; box-sizing: border-box"
|
||||
text="360儿童电话手表9X 智能语音问答定位支付手表 4G全网通20米游泳级防水视频通话拍照手表男女孩星空蓝"
|
||||
></l-painter-text>
|
||||
<l-painter-qrcode
|
||||
css="width: 128rpx; height: 128rpx;"
|
||||
text="limeui.qcoon.cn"
|
||||
></l-painter-qrcode>
|
||||
</l-painter-view>
|
||||
</l-painter-view>
|
||||
</l-painter>
|
||||
```
|
||||
|
||||
```js
|
||||
data() {
|
||||
return {
|
||||
path: ''
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 方式二 JSON
|
||||
|
||||
```html
|
||||
<image :src="path" mode="widthFix"></image>
|
||||
<l-painter
|
||||
:board="poster"
|
||||
isCanvasToTempFilePath
|
||||
@success="path = $event"
|
||||
hidden
|
||||
/>
|
||||
```
|
||||
|
||||
```js
|
||||
data() {
|
||||
return {
|
||||
path: '',
|
||||
poster: {
|
||||
css: {
|
||||
width: "750rpx",
|
||||
paddingBottom: "40rpx",
|
||||
background: "linear-gradient(,#000 0%, #ff5000 100%)"
|
||||
},
|
||||
views: [
|
||||
{
|
||||
src: "https://m.360buyimg.com/babel/jfs/t1/196317/32/13733/288158/60f4ea39E6fb378ed/d69205b1a8ed3c97.jpg",
|
||||
type: "image",
|
||||
css: {
|
||||
background: "#fff",
|
||||
objectFit: "cover",
|
||||
marginLeft: "40rpx",
|
||||
marginTop: "40rpx",
|
||||
width: "84rpx",
|
||||
border: "2rpx solid #fff",
|
||||
boxSizing: "border-box",
|
||||
height: "84rpx",
|
||||
borderRadius: "50%"
|
||||
}
|
||||
},
|
||||
{
|
||||
type: "view",
|
||||
css: {
|
||||
marginTop: "40rpx",
|
||||
paddingLeft: "20rpx",
|
||||
display: "inline-block"
|
||||
},
|
||||
views: [
|
||||
{
|
||||
text: "隔壁老王",
|
||||
type: "text",
|
||||
css: {
|
||||
display: "block",
|
||||
paddingBottom: "10rpx",
|
||||
color: "#fff",
|
||||
fontSize: "32rpx",
|
||||
fontWeight: "bold"
|
||||
}
|
||||
},
|
||||
{
|
||||
text: "为您挑选了一个好物",
|
||||
type: "text",
|
||||
css: {
|
||||
color: "rgba(255,255,255,.7)",
|
||||
fontSize: "24rpx"
|
||||
},
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
css: {
|
||||
marginLeft: "40rpx",
|
||||
marginTop: "30rpx",
|
||||
padding: "32rpx",
|
||||
boxSizing: "border-box",
|
||||
background: "#fff",
|
||||
borderRadius: "16rpx",
|
||||
width: "670rpx",
|
||||
boxShadow: "0 20rpx 58rpx rgba(0,0,0,.15)"
|
||||
},
|
||||
views: [
|
||||
{
|
||||
src: "https://m.360buyimg.com/babel/jfs/t1/196317/32/13733/288158/60f4ea39E6fb378ed/d69205b1a8ed3c97.jpg",
|
||||
type: "image",
|
||||
css: {
|
||||
objectFit: "cover",
|
||||
objectPosition: "50% 50%",
|
||||
width: "606rpx",
|
||||
height: "606rpx"
|
||||
},
|
||||
}, {
|
||||
css: {
|
||||
marginTop: "32rpx",
|
||||
color: "#FF0000",
|
||||
fontWeight: "bold",
|
||||
fontSize: "28rpx",
|
||||
lineHeight: "1em"
|
||||
},
|
||||
views: [{
|
||||
text: "¥",
|
||||
type: "text",
|
||||
css: {
|
||||
verticalAlign: "bottom"
|
||||
},
|
||||
}, {
|
||||
text: "39",
|
||||
type: "text",
|
||||
css: {
|
||||
verticalAlign: "bottom",
|
||||
fontSize: "58rpx"
|
||||
},
|
||||
}, {
|
||||
text: ".39",
|
||||
type: "text",
|
||||
css: {
|
||||
verticalAlign: "bottom"
|
||||
},
|
||||
}, {
|
||||
text: "¥59.99",
|
||||
type: "text",
|
||||
css: {
|
||||
verticalAlign: "bottom",
|
||||
paddingLeft: "10rpx",
|
||||
fontWeight: "normal",
|
||||
textDecoration: "line-through",
|
||||
color: "#999999"
|
||||
}
|
||||
}],
|
||||
|
||||
type: "view"
|
||||
}, {
|
||||
css: {
|
||||
marginTop: "32rpx",
|
||||
fontSize: "26rpx",
|
||||
color: "#8c5400"
|
||||
},
|
||||
views: [{
|
||||
text: "自营",
|
||||
type: "text",
|
||||
css: {
|
||||
color: "#212121",
|
||||
background: "#ffb400"
|
||||
},
|
||||
}, {
|
||||
text: "30天最低价",
|
||||
type: "text",
|
||||
css: {
|
||||
marginLeft: "16rpx",
|
||||
background: "#fff4d9",
|
||||
textDecoration: "line-through"
|
||||
},
|
||||
}, {
|
||||
text: "满减优惠",
|
||||
type: "text",
|
||||
css: {
|
||||
marginLeft: "16rpx",
|
||||
background: "#fff4d9"
|
||||
},
|
||||
}, {
|
||||
text: "超高好评",
|
||||
type: "text",
|
||||
css: {
|
||||
marginLeft: "16rpx",
|
||||
background: "#fff4d9"
|
||||
},
|
||||
|
||||
}],
|
||||
|
||||
type: "view"
|
||||
}, {
|
||||
css: {
|
||||
marginTop: "30rpx"
|
||||
},
|
||||
views: [
|
||||
{
|
||||
text: "360儿童电话手表9X 智能语音问答定位支付手表 4G全网通20米游泳级防水视频通话拍照手表男女孩星空蓝",
|
||||
type: "text",
|
||||
css: {
|
||||
paddingRight: "32rpx",
|
||||
boxSizing: "border-box",
|
||||
lineClamp: 2,
|
||||
color: "#333333",
|
||||
lineHeight: "1.8em",
|
||||
fontSize: "36rpx",
|
||||
width: "478rpx"
|
||||
},
|
||||
}, {
|
||||
text: "limeui.qcoon.cn",
|
||||
type: "qrcode",
|
||||
css: {
|
||||
width: "128rpx",
|
||||
height: "128rpx",
|
||||
},
|
||||
|
||||
}],
|
||||
type: "view"
|
||||
}],
|
||||
type: "view"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### 自定义字体
|
||||
- 需要平台的支持,已知微信小程序支持,其它的没试过,如果可行请告之
|
||||
|
||||
```
|
||||
// 需要在app.vue中下载字体
|
||||
uni.loadFontFace({
|
||||
global:true,
|
||||
scopes: ['native'],
|
||||
family: '自定义字体名称',
|
||||
source: 'url("https://sungd.github.io/Pacifico.ttf")',
|
||||
|
||||
success() {
|
||||
console.log('success')
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
// 然后就可以在插件的css中写font-family: '自定义字体名称'
|
||||
```
|
||||
|
||||
|
||||
### Nvue
|
||||
- 必须为HBX 3.4.11及以上
|
||||
|
||||
|
||||
### 原生小程序
|
||||
|
||||
- 插件里的`painter.js`支持在原生小程序中使用
|
||||
- new Painter 之后在`source`里传入 JSON
|
||||
- 再调用`render`绘制海报
|
||||
- 如需生成图片,请查看微信小程序 cavnas 的[canvasToTempFilePath](https://developers.weixin.qq.com/miniprogram/dev/api/canvas/wx.canvasToTempFilePath.html)
|
||||
|
||||
```html
|
||||
<canvas type="2d" id="painter" style="width: 100%"></canvas>
|
||||
```
|
||||
|
||||
```js
|
||||
import { Painter } from "./painter";
|
||||
page({
|
||||
data: {
|
||||
poster: {
|
||||
css: {
|
||||
width: "750rpx",
|
||||
},
|
||||
views: [
|
||||
{
|
||||
type: "view",
|
||||
css: {
|
||||
background: "#d2d4c8",
|
||||
paddingTop: "100rpx",
|
||||
},
|
||||
views: [
|
||||
{
|
||||
type: "view",
|
||||
css: {
|
||||
background: "#5f7470",
|
||||
width: "33.33%",
|
||||
height: "100rpx",
|
||||
display: "inline-block",
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "view",
|
||||
css: {
|
||||
background: "#889696",
|
||||
width: "33.33%",
|
||||
height: "100rpx",
|
||||
display: "inline-block",
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "view",
|
||||
css: {
|
||||
background: "#b8bdb5",
|
||||
width: "33.33%",
|
||||
height: "100rpx",
|
||||
display: "inline-block",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
async onLoad() {
|
||||
const res = await this.getCentext();
|
||||
const painter = new Painter(res);
|
||||
// 返回计算布局后的整个内容尺寸
|
||||
const { width, height } = await painter.source(this.data.poster);
|
||||
// 得到计算后的尺寸后 可给canvas尺寸赋值,达到动态响应效果
|
||||
// 渲染
|
||||
await painter.render();
|
||||
},
|
||||
// 获取canvas 2d
|
||||
// 非2d 需要传一个 createImage 方法用于获取图片信息 即把 getImageInfo 的 success 通过 promise resolve 返回
|
||||
getCentext() {
|
||||
return new Promise((resolve) => {
|
||||
wx.createSelectorQuery()
|
||||
.select(`#painter`)
|
||||
.node()
|
||||
.exec((res) => {
|
||||
let { node: canvas } = res[0];
|
||||
resolve({
|
||||
canvas,
|
||||
context: canvas.getContext("2d"),
|
||||
width: canvas.width,
|
||||
height: canvas.height,
|
||||
// createImage: getImageInfo()
|
||||
pixelRatio: 2,
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
### 旧版(1.6.x)更新
|
||||
|
||||
- 由于 1.8.x 版放弃了以定位的方式,所以 1.6.x 版更新之后要每个样式都加上`position: absolute`
|
||||
- 旧版的 `image` mode 模式被放弃,使用`object-fit`
|
||||
- 旧版的 `isRenderImage` 改成 `is-canvas-to-temp-file-path`
|
||||
- 旧版的 `maxLines` 改成 `line-clamp`
|
||||
|
||||
## API
|
||||
|
||||
### Props
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
| -------------------------- | ------------------------------------------------------------ | ---------------- | ------------ |
|
||||
| board | JSON 方式的海报元素对象集 | <em>object</em> | - |
|
||||
| css | 海报内容最外层的样式,可以理解为`body` | <em>object</em> | 参数请向下看 |
|
||||
| custom-style | canvas 元素的样式 | <em>string</em> | |
|
||||
| hidden | 隐藏画板 | <em>boolean</em> | `false` |
|
||||
| is-canvas-to-temp-file-path | 是否生成图片,在`@success`事件接收图片地址 | <em>boolean</em> | `false` |
|
||||
| after-delay | 生成图片错乱,可延时生成图片 | <em>number</em> | `100` |
|
||||
| type | canvas 类型,对微信头条支付宝小程序可有效,可选值:`2d`,`''` | <em>string</em> | `2d` |
|
||||
| file-type | 生成图片的后缀类型, 可选值:`png`、`jpg` | <em>string</em> | `png` |
|
||||
| path-type | 生成图片路径类型,可选值`url`、`base64` | <em>string</em> | `-` |
|
||||
| pixel-ratio | 生成图片的像素密度,默认为对应手机的像素密度,`nvue`无效 | <em>number</em> | `-` |
|
||||
| hidpi | H5和APP是否使用高清处理 | <em>boolean</em> | `true` |
|
||||
| width | **废弃** 画板的宽度,一般只用于通过内部方法时加上 | <em>number</em> | `` |
|
||||
| height | **废弃** 画板的高度 ,同上 | <em>number</em> | `` |
|
||||
|
||||
### css
|
||||
| 属性名 | 支持的值或类型 | 默认值 |
|
||||
| ----------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------- |
|
||||
| (min\max)width | 支持`%`、`rpx`、`px` | - |
|
||||
| height | 同上 | - |
|
||||
| color | `string` | - |
|
||||
| position | 定位,可选值:`absolute`、`fixed` | - |
|
||||
| ↳ left、top、right、bottom | 配合`position`才生效,支持`%`、`rpx`、`px` | - |
|
||||
| margin | 可简写或各方向分别写,如:`margin-top`,支持`auto`、`rpx`、`px` | - |
|
||||
| padding | 可简写或各方向分别写,支持`rpx`、`px` | - |
|
||||
| border | 可简写或各个值分开写:`border-width`、`border-style` 、`border-color`,简写请按顺序写 | - |
|
||||
| line-clamp | `number`,超过行数显示省略号 | - |
|
||||
| vertical-align | 文字垂直对齐,可选值:`bottom`、`top`、`middle` | `middle` |
|
||||
| line-height | 文字行高,支持`rpx`、`px`、`em` | `1.4em` |
|
||||
| font-weight | 文字粗细,可选值:`normal`、`bold` | `normal` |
|
||||
| font-size | 文字大小,`string`,支持`rpx`、`px` | `14px` |
|
||||
| text-decoration | 文本修饰,可选值:`underline` 、`line-through`、`overline` | - |
|
||||
| text-stroke | 文字描边,可简写或各个值分开写,如:`text-stroke-color`, `text-stroke-width` | - |
|
||||
| text-align | 文本水平对齐,可选值:`right` 、`center` | `left` |
|
||||
| display | 框类型,可选值:`block`、`inline-block`、`flex`、`none`,当为`none`时是不渲染该段, `flex`功能简陋。 | - |
|
||||
| flex | 配合 display: flex; 属性定义了在分配多余空间,目前只用为数值如: flex: 1 | - |
|
||||
| align-self | 配合 display: flex; 单个项目垂直轴对齐方式: `flex-start` `flex-end` `center` | `flex-start` |
|
||||
| justify-content | 配合 display: flex; 水平轴对齐方式: `flex-start` `flex-end` `center` | `flex-start` |
|
||||
| align-items | 配合 display: flex; 垂直轴对齐方式: `flex-start` `flex-end` `center` | `flex-start` |
|
||||
| border-radius | 圆角边框,支持`%`、`rpx`、`px` | - |
|
||||
| box-sizing | 可选值:`border-box` | - |
|
||||
| box-shadow | 投影 | - |
|
||||
| background(color) | 支持渐变,但必须写百分比!如:`linear-gradient(,#ff971b 0%, #ff5000 100%)`、`radial-gradient(#0ff 15%, #f0f 60%)`,目前 radial-gradient 渐变的圆心为元素中点,半径为最长边,不支持设置 | - |
|
||||
| background-clip | 文字渐变,配合`background`背景渐变,设置`background-clip: text` 达到文字渐变效果 | - |
|
||||
| background-image | view 元素背景:`url(src)`,若只是设置背景图,请不要设置`background-repeat` | - |
|
||||
| background-repeat | 设置是否及如何重复背景纹理,可选值:`repeat`、`repeat-x`、`repeat-y`、`no-repeat` | `repeat` |
|
||||
| [object-fit](https://developer.mozilla.org/zh-CN/docs/Web/CSS/object-fit/) | 图片元素适应容器方式,类似于`mode`,可选值:`cover`、 `contain`、 `fill`、 `none` | - |
|
||||
| [object-position](https://developer.mozilla.org/zh-CN/docs/Web/CSS/object-position) | 图片的对齐方式,配合`object-fit`使用 | - |
|
||||
|
||||
### 图片填充模式 object-fit
|
||||
|
||||
| 名称 | 含义 |
|
||||
| ------- | ------------------------------------------------------ |
|
||||
| contain | 保持宽高缩放图片,使图片的长边能完全显示出来 |
|
||||
| cover | 保持宽高缩放图片,使图片的短边能完全显示出来,裁剪长边 |
|
||||
| fill | 拉伸图片,使图片填满元素 |
|
||||
| none | 保持图片原有尺寸 |
|
||||
|
||||
### 事件 Events
|
||||
|
||||
| 事件名 | 说明 | 返回值 |
|
||||
| -------- | ---------------------------------------------------------------- | ------ |
|
||||
| success | 生成图片成功,若使用`is-canvas-to-temp-filePath` 可以接收图片地址 | path |
|
||||
| fail | 生成图片失败 | error |
|
||||
| done | 绘制成功 | |
|
||||
| progress | 绘制进度 | number |
|
||||
|
||||
### 暴露函数 Expose
|
||||
| 事件名 | 说明 | 返回值 |
|
||||
| -------- | ---------------------------------------------------------------- | ------ |
|
||||
| render(object) | 渲染器,传入JSON 绘制海报 | promise |
|
||||
| [canvasToTempFilePath](https://uniapp.dcloud.io/api/canvas/canvasToTempFilePath.html#canvastotempfilepath)(object) | 把当前画布指定区域的内容导出生成指定大小的图片,并返回文件临时路径。 | |
|
||||
| canvasToTempFilePathSync(object) | 同步接口,同上 | |
|
||||
|
||||
|
||||
## 常见问题
|
||||
|
||||
- 1、H5 端使用网络图片需要解决跨域问题。
|
||||
- 2、小程序使用网络图片需要去公众平台增加下载白名单!二级域名也需要配!
|
||||
- 3、H5 端生成图片是 base64,有时显示只有一半可以使用原生标签`<IMG/>`
|
||||
- 4、发生保存图片倾斜变形或提示 native buffer exceed size limit 时,使用 pixel-ratio="2"参数,降分辨率。
|
||||
- 5、h5 保存图片不需要调接口,提示用户长按图片保存。
|
||||
- 6、画板不能隐藏,包括`v-if`,`v-show`、`display:none`、`opacity:0`,另外也不要把画板放在弹窗里。如果需要隐藏画板请设置 `custom-style="position: fixed; left: 200%"`
|
||||
- 7、微信小程序真机调试请使用 **真机调试2.0**,不支持1.0。
|
||||
- 8、微信小程序打开调试时可以生但并闭无法生成时,这种情况一般是没有在公众号配置download域名
|
||||
- 9、HBX 3.4.5之前的版本不支持vue3
|
||||
- 10、在微信开发工具上 canvas 层级最高无法zindex,并不影响真机
|
||||
- 11、请不要导入非uni_modules插件
|
||||
- 12、关于QQ小程序 报 Propertyor method"toJSON"is not defined 请把基础库调到 1.50.3
|
||||
- 13、支付宝小程序 IDE 不支持 生成图片 请以真机调试结果为准
|
||||
- 14、返回值为字符串 `data:,` 大概是尺寸超过限制,设置 pixel-ratio="2"
|
||||
- 华为手机 APP 上无法生成图片,请使用 HBX2.9.11++(已过时,忽略这条)
|
||||
- IOS APP 请勿使用 HBX2.9.3.20201014 的版本!这个版本无法生成图片。(已过时,忽略这条)
|
||||
- 苹果微信 7.0.20 存在闪退和图片无法 onload 为微信 bug(已过时,忽略这条)
|
||||
- 微信小程序 IOS 旧接口 如父级设置圆角,子级也设会导致子级的失效,为旧接口BUG。
|
||||
- 微信小程序 安卓 旧接口 如使用图片必须加背景色,为旧接口BUG。
|
||||
- 微信小程序 安卓端 [图片可能在首次可以加载成功,再次加载会不触发任何事件](https://developers.weixin.qq.com/community/develop/doc/000ee2b8dacf4009337f51f4556800?highLine=canvas%25202d%2520createImage),临时解决方法是给图片加个时间戳
|
||||
## 打赏
|
||||
|
||||
如果你觉得本插件,解决了你的问题,赠人玫瑰,手留余香。
|
||||
|
||||

|
||||

|
320
uni_modules/qiun-data-charts/changelog.md
Normal file
320
uni_modules/qiun-data-charts/changelog.md
Normal file
@ -0,0 +1,320 @@
|
||||
## 2.5.0-20230101(2023-01-01)
|
||||
- 秋云图表组件 修改条件编译顺序,确保uniapp的cli方式的项目依赖不完整时可以正常显示
|
||||
- 秋云图表组件 恢复props属性directory的使用,以修复vue3项目中,开启echarts后,echarts目录识别错误的bug
|
||||
- uCharts.js 修复区域图、混合图只有一个数据时图表显示不正确的bug
|
||||
- uCharts.js 修复折线图、区域图中时间轴类别图表tooltip指示点显示不正确的bug
|
||||
- uCharts.js 修复x轴使用labelCount时,并且boundaryGap = 'justify' 并且关闭Y轴显示的时候,最后一个坐标值不显示的bug
|
||||
- uCharts.js 修复折线图只有一组数据时 ios16 渲染颜色不正确的bug
|
||||
- uCharts.js 修复玫瑰图半径显示不正确的bug
|
||||
- uCharts.js 柱状图、山峰图增加正负图功能,y轴网格如果需要显示0轴则由 min max 及 splitNumber 确定,后续版本优化自动显示0轴
|
||||
- uCharts.js 柱状图column增加 opts.extra.column.labelPosition,数据标签位置,有效值为 outside外部, insideTop内顶部, center内中间, bottom内底部
|
||||
- uCharts.js 雷达图radar增加 opts.extra.radar.labelShow,否显示各项标识文案是,默认true
|
||||
- uCharts.js 提示窗tooltip增加 opts.extra.tooltip.boxPadding,提示窗边框填充距离,默认3px
|
||||
- uCharts.js 提示窗tooltip增加 opts.extra.tooltip.fontSize,提示窗字体大小配置,默认13px
|
||||
- uCharts.js 提示窗tooltip增加 opts.extra.tooltip.lineHeight,提示窗文字行高,默认20px
|
||||
- uCharts.js 提示窗tooltip增加 opts.extra.tooltip.legendShow,是否显示左侧图例,默认true
|
||||
- uCharts.js 提示窗tooltip增加 opts.extra.tooltip.legendShape,图例形状,图例标识样式,有效值为 auto自动跟随图例, diamond◆, circle●, triangle▲, square■, rect▬, line-
|
||||
- uCharts.js 标记线markLine增加 opts.extra.markLine.labelFontSize,字体大小配置,默认13px
|
||||
- uCharts.js 标记线markLine增加 opts.extra.markLine.labelPadding,标签边框内填充距离,默认6px
|
||||
- uCharts.js 折线图line增加 opts.extra.line.linearType,渐变色类型,可选值 none关闭渐变色,custom 自定义渐变色。使用自定义渐变色时请赋值serie.linearColor作为颜色值
|
||||
- uCharts.js 折线图line增加 serie.linearColor,渐变色数组,格式为2维数组[起始位置,颜色值],例如[[0,'#0EE2F8'],[0.3,'#2BDCA8'],[0.6,'#1890FF'],[1,'#9A60B4']]
|
||||
- uCharts.js 折线图line增加 opts.extra.line.onShadow,是否开启折线阴影,开启后请赋值serie.setShadow阴影设置
|
||||
- uCharts.js 折线图line增加 serie.setShadow,阴影配置,格式为4位数组:[offsetX,offsetY,blur,color]
|
||||
- uCharts.js 折线图line增加 opts.extra.line.animation,动画效果方向,可选值为vertical 垂直动画效果,horizontal 水平动画效果
|
||||
- uCharts.js X轴xAxis增加 opts.xAxis.lineHeight,X轴字体行高,默认20px
|
||||
- uCharts.js X轴xAxis增加 opts.xAxis.marginTop,X轴文字距离轴线的距离,默认0px
|
||||
- uCharts.js X轴xAxis增加 opts.xAxis.title,当前X轴标题
|
||||
- uCharts.js X轴xAxis增加 opts.xAxis.titleFontSize,标题字体大小,默认13px
|
||||
- uCharts.js X轴xAxis增加 opts.xAxis.titleOffsetY,标题纵向偏移距离,负数为向上偏移,正数向下偏移
|
||||
- uCharts.js X轴xAxis增加 opts.xAxis.titleOffsetX,标题横向偏移距离,负数为向左偏移,正数向右偏移
|
||||
- uCharts.js X轴xAxis增加 opts.xAxis.titleFontColor,标题字体颜色,默认#666666
|
||||
|
||||
## 报错TypeError: Cannot read properties of undefined (reading 'length')
|
||||
- 如果是uni-modules版本组件,请先登录HBuilderX账号;
|
||||
- 在HBuilderX中的manifest.json,点击重新获取uniapp的appid,或者删除appid重新粘贴,重新运行;
|
||||
- 如果是cli项目请使用码云上的非uniCloud版本组件;
|
||||
- 或者添加uniCloud的依赖;
|
||||
- 或者使用原生uCharts;
|
||||
## 2.4.5-20221130(2022-11-30)
|
||||
- uCharts.js 优化tooltip当文字很多变为左侧显示时,如果画布仍显显示不下,提示框错位置变为以左侧0位置起画
|
||||
- uCharts.js 折线图修复特殊情况下只有单点数据,并改变线宽后点变为圆形的bug
|
||||
- uCharts.js 修复Y轴disabled启用后无效并报错的bug
|
||||
- uCharts.js 修复仪表盘起始结束角度特殊情况下显示不正确的bug
|
||||
- uCharts.js 雷达图新增参数 opts.extra.radar.radius , 自定义雷达图半径
|
||||
- uCharts.js 折线图、区域图增加tooltip指示点,opts.extra.line.activeType/opts.extra.area.activeType,可选值"none"不启用激活指示点,"hollow"空心点模式,"solid"实心点模式
|
||||
## 2.4.4-20221102(2022-11-02)
|
||||
- 秋云图表组件 修复使用echarts时reload、reshow无法调用重新渲染的bug,[详见码云PR](https://gitee.com/uCharts/uCharts/pulls/40)
|
||||
- 秋云图表组件 修复使用echarts时,初始化时宽高不正确的bug,[详见码云PR](https://gitee.com/uCharts/uCharts/pulls/42)
|
||||
- 秋云图表组件 修复uniapp的h5使用history模式时,无法加载echarts的bug
|
||||
- 秋云图表组件 小程序端@complete、@scrollLeft、@scrollRight、@getTouchStart、@getTouchMove、@getTouchEnd事件增加opts参数传出,方便一些特殊需求的交互获取数据。
|
||||
|
||||
- uCharts.js 修复calTooltipYAxisData方法内formatter格式化方法未与y轴方法同步的问题,[详见码云PR](https://gitee.com/uCharts/uCharts/pulls/43)
|
||||
- uCharts.js 地图新增参数opts.series[i].fillOpacity,以透明度方式来设置颜色过度效果,[详见码云PR](https://gitee.com/uCharts/uCharts/pulls/38)
|
||||
- uCharts.js 地图新增参数opts.extra.map.active,是否启用点击激活变色
|
||||
- uCharts.js 地图新增参数opts.extra.map.activeTextColor,是否启用点击激活变色
|
||||
- uCharts.js 地图新增渲染完成事件renderComplete
|
||||
- uCharts.js 漏斗图修复当部分数据相同时tooltip提示窗点击错误的bug
|
||||
- uCharts.js 漏斗图新增参数series.data[i].centerText 居中标签文案
|
||||
- uCharts.js 漏斗图新增参数series.data[i].centerTextSize 居中标签文案字体大小,默认opts.fontSize
|
||||
- uCharts.js 漏斗图新增参数series.data[i].centerTextColor 居中标签文案字体颜色,默认#FFFFFF
|
||||
- uCharts.js 漏斗图新增参数opts.extra.funnel.minSize 最小值的最小宽度,默认0
|
||||
- uCharts.js 进度条新增参数opts.extra.arcbar.direction,动画方向,可选值为cw顺时针、ccw逆时针
|
||||
- uCharts.js 混合图新增参数opts.extra.mix.line.width,折线的宽度,默认2
|
||||
- uCharts.js 修复tooltip开启horizentalLine水平横线标注时,图表显示错位的bug
|
||||
- uCharts.js 优化tooltip当文字很多变为左侧显示时,如果画布仍显显示不下,提示框错位置变为以左侧0位置起画
|
||||
- uCharts.js 修复开启滚动条后X轴文字超出绘图区域后的隐藏逻辑
|
||||
- uCharts.js 柱状图、条状图修复堆叠模式不能通过{value,color}赋值单个柱子颜色的问题
|
||||
- uCharts.js 气泡图修复不识别series.textSize和series.textColor的bug
|
||||
|
||||
## 报错TypeError: Cannot read properties of undefined (reading 'length')
|
||||
1. 如果是uni-modules版本组件,请先登录HBuilderX账号;
|
||||
2. 在HBuilderX中的manifest.json,点击重新获取uniapp的appid,或者删除appid重新粘贴,重新运行;
|
||||
3. 如果是cli项目请使用码云上的非uniCloud版本组件;
|
||||
4. 或者添加uniCloud的依赖;
|
||||
5. 或者使用原生uCharts;
|
||||
## 2.4.3-20220505(2022-05-05)
|
||||
- 秋云图表组件 修复开启canvas2d后将series赋值为空数组显示加载图标时,再次赋值后画布闪动的bug
|
||||
- 秋云图表组件 修复升级hbx最新版后ECharts的highlight方法报错的bug
|
||||
- uCharts.js 雷达图新增参数opts.extra.radar.gridEval,数据点位网格抽希,默认1
|
||||
- uCharts.js 雷达图新增参数opts.extra.radar.axisLabel, 是否显示刻度点值,默认false
|
||||
- uCharts.js 雷达图新增参数opts.extra.radar.axisLabelTofix,刻度点值小数位数,默认0
|
||||
- uCharts.js 雷达图新增参数opts.extra.radar.labelPointShow,是否显示末端刻度圆点,默认false
|
||||
- uCharts.js 雷达图新增参数opts.extra.radar.labelPointRadius,刻度圆点的半径,默认3
|
||||
- uCharts.js 雷达图新增参数opts.extra.radar.labelPointColor,刻度圆点的颜色,默认#cccccc
|
||||
- uCharts.js 雷达图新增参数opts.extra.radar.linearType,渐变色类型,可选值"none"关闭渐变,"custom"开启渐变
|
||||
- uCharts.js 雷达图新增参数opts.extra.radar.customColor,自定义渐变颜色,数组类型对应series的数组长度以匹配不同series颜色的不同配色方案,例如["#FA7D8D", "#EB88E2"]
|
||||
- uCharts.js 雷达图优化支持series.textColor、series.textSize属性
|
||||
- uCharts.js 柱状图中温度计式图标,优化支持全圆角类型,修复边框有缝隙的bug,详见官网【演示】中的温度计图表
|
||||
- uCharts.js 柱状图新增参数opts.extra.column.activeWidth,当前点击柱状图的背景宽度,默认一个单元格单位
|
||||
- uCharts.js 混合图增加opts.extra.mix.area.gradient 区域图是否开启渐变色
|
||||
- uCharts.js 混合图增加opts.extra.mix.area.opacity 区域图透明度,默认0.2
|
||||
- uCharts.js 饼图、圆环图、玫瑰图、漏斗图,增加opts.series[0].data[i].labelText,自定义标签文字,避免formatter格式化的繁琐,详见官网【演示】中的饼图
|
||||
- uCharts.js 饼图、圆环图、玫瑰图、漏斗图,增加opts.series[0].data[i].labelShow,自定义是否显示某一个指示标签,避免因饼图类别太多导致标签重复或者居多导致图形变形的问题,详见官网【演示】中的饼图
|
||||
- uCharts.js 增加opts.series[i].legendText/opts.series[0].data[i].legendText(与series.name同级)自定义图例显示文字的方法
|
||||
- uCharts.js 优化X轴、Y轴formatter格式化方法增加形参,统一为fromatter:function(value,index,opts){}
|
||||
- uCharts.js 修复横屏模式下无法使用双指缩放方法的bug
|
||||
- uCharts.js 修复当只有一条数据或者多条数据值相等的时候Y轴自动计算的最大值错误的bug
|
||||
- 【官网模板】增加外部自定义图例与图表交互的例子,[点击跳转](https://www.ucharts.cn/v2/#/layout/info?id=2)
|
||||
|
||||
## 注意:非unimodules 版本如因更新 hbx 至 3.4.7 导致报错如下,请到码云更新非 unimodules 版本组件,[点击跳转](https://gitee.com/uCharts/uCharts/tree/master/uni-app/uCharts-%E7%BB%84%E4%BB%B6)
|
||||
> Error in callback for immediate watcher "uchartsOpts": "SyntaxError: Unexpected token u in JSON at position 0"
|
||||
## 2.4.2-20220421(2022-04-21)
|
||||
- 秋云图表组件 修复HBX升级3.4.6.20220420版本后echarts报错的问题
|
||||
## 2.4.2-20220420(2022-04-20)
|
||||
## 重要!此版本uCharts新增了很多功能,修复了诸多已知问题
|
||||
- 秋云图表组件 新增onzoom开启双指缩放功能(仅uCharts),前提需要直角坐标系类图表类型,并且ontouch为true、opts.enableScroll为true,详见实例项目K线图
|
||||
- 秋云图表组件 新增optsWatch是否监听opts变化,关闭optsWatch后,动态修改opts不会触发图表重绘
|
||||
- 秋云图表组件 修复开启canvas2d功能后,动态更新数据后画布闪动的bug
|
||||
- 秋云图表组件 去除directory属性,改为自动获取echarts.min.js路径(升级不受影响)
|
||||
- 秋云图表组件 增加getImage()方法及@getImage事件,通过ref调用getImage()方法获,触发@getImage事件获取当前画布的base64图片文件流。
|
||||
- 秋云图表组件 支付宝、字节跳动、飞书、快手小程序支持开启canvas2d同层渲染设置。
|
||||
- 秋云图表组件 新增加【非uniCloud】版本组件,避免有些不需要uniCloud的使用组件发布至小程序需要提交隐私声明问题,请到码云[【非uniCloud版本】](https://gitee.com/uCharts/uCharts/tree/master/uni-app/uCharts-%E7%BB%84%E4%BB%B6),或npm[【非uniCloud版本】](https://www.npmjs.com/package/@qiun/uni-ucharts)下载使用。
|
||||
- uCharts.js 新增dobuleZoom双指缩放功能
|
||||
- uCharts.js 新增山峰图type="mount",数据格式为饼图类格式,不需要传入categories,具体详见新版官网在线演示
|
||||
- uCharts.js 修复折线图当数据中存在null时tooltip报错的bug
|
||||
- uCharts.js 修复饼图类当画布比较小时自动计算的半径是负数报错的bug
|
||||
- uCharts.js 统一各图表类型的series.formatter格式化方法的形参为(val, index, series, opts),方便格式化时有更多参数可用
|
||||
- uCharts.js 标记线功能增加labelText自定义显示文字,增加labelAlign标签显示位置(左侧或右侧),增加标签显示位置微调labelOffsetX、labelOffsetY
|
||||
- uCharts.js 修复条状图当数值很小时开启圆角后样式错误的bug
|
||||
- uCharts.js 修复X轴开启disabled后,X轴仍占用空间的bug
|
||||
- uCharts.js 修复X轴开启滚动条并且开启rotateLabel后,X轴文字与滚动条重叠的bug
|
||||
- uCharts.js 增加X轴rotateAngle文字旋转自定义角度,取值范围(-90至90)
|
||||
- uCharts.js 修复地图文字标签层级显示不正确的bug
|
||||
- uCharts.js 修复饼图、圆环图、玫瑰图当数据全部为0的时候不显示数据标签的bug
|
||||
- uCharts.js 修复当opts.padding上边距为0时,Y轴顶部刻度标签位置不正确的bug
|
||||
|
||||
## 另外我们还开发了各大原生小程序组件,已发布至码云和npm
|
||||
[https://gitee.com/uCharts/uCharts](https://gitee.com/uCharts/uCharts)
|
||||
[https://www.npmjs.com/~qiun](https://www.npmjs.com/~qiun)
|
||||
|
||||
## 对于原生uCharts文档我们已上线新版官方网站,详情点击下面链接进入官网
|
||||
[https://www.uCharts.cn/v2/](https://www.ucharts.cn/v2/)
|
||||
## 2.3.7-20220122(2022-01-22)
|
||||
## 重要!使用vue3编译,请使用cli模式并升级至最新依赖,HbuilderX编译需要使用3.3.8以上版本
|
||||
- uCharts.js 修复uni-app平台组件模式使用vue3编译到小程序报错的bug。
|
||||
## 2.3.7-20220118(2022-01-18)
|
||||
## 注意,使用vue3的前提是需要3.3.8.20220114-alpha版本的HBuilder!
|
||||
## 2.3.67-20220118(2022-01-18)
|
||||
- 秋云图表组件 组件初步支持vue3,全端编译会有些问题,具体详见下面修改:
|
||||
1. 小程序端运行时,在uni_modules文件夹的qiun-data-charts.js中搜索 new uni_modules_qiunDataCharts_js_sdk_uCharts_uCharts.uCharts,将.uCharts去掉。
|
||||
2. 小程序端发行时,在uni_modules文件夹的qiun-data-charts.js中搜索 new e.uCharts,将.uCharts去掉,变为 new e。
|
||||
3. 如果觉得上述步骤比较麻烦,如果您的项目只编译到小程序端,可以修改u-charts.js最后一行导出方式,将 export default uCharts;变更为 export default { uCharts: uCharts }; 这样变更后,H5和App端的renderjs会有问题,请开发者自行选择。(此问题非组件问题,请等待DC官方修复Vue3的小程序端)
|
||||
## 2.3.6-20220111(2022-01-11)
|
||||
- 秋云图表组件 修改组件 props 属性中的 background 默认值为 rgba(0,0,0,0)
|
||||
## 2.3.6-20211201(2021-12-01)
|
||||
- uCharts.js 修复bar条状图开启圆角模式时,值很小时圆角渲染错误的bug
|
||||
## 2.3.5-20211014(2021-10-15)
|
||||
- uCharts.js 增加vue3的编译支持(仅原生uCharts,qiun-data-charts组件后续会支持,请关注更新)
|
||||
## 2.3.4-20211012(2021-10-12)
|
||||
- 秋云图表组件 修复 mac os x 系统 mouseover 事件丢失的 bug
|
||||
## 2.3.3-20210706(2021-07-06)
|
||||
- uCharts.js 增加雷达图开启数据点值(opts.dataLabel)的显示
|
||||
## 2.3.2-20210627(2021-06-27)
|
||||
- 秋云图表组件 修复tooltipCustom个别情况下传值不正确报错TypeError: Cannot read property 'name' of undefined的bug
|
||||
## 2.3.1-20210616(2021-06-16)
|
||||
- uCharts.js 修复圆角柱状图使用4角圆角时,当数值过大时不正确的bug
|
||||
## 2.3.0-20210612(2021-06-12)
|
||||
- uCharts.js 【重要】uCharts增加nvue兼容,可在nvue项目中使用gcanvas组件渲染uCharts,[详见码云uCharts-demo-nvue](https://gitee.com/uCharts/uCharts)
|
||||
- 秋云图表组件 增加tapLegend属性,是否开启图例点击交互事件
|
||||
- 秋云图表组件 getIndex事件中增加返回uCharts实例中的opts参数,以便在页面中调用参数
|
||||
- 示例项目 pages/other/other.vue增加app端自定义tooltip的方法,详见showOptsTooltip方法
|
||||
## 2.2.1-20210603(2021-06-03)
|
||||
- uCharts.js 修复饼图、圆环图、玫瑰图,当起始角度不为0时,tooltip位置不准确的bug
|
||||
- uCharts.js 增加温度计式柱状图开启顶部半圆形的配置
|
||||
## 2.2.0-20210529(2021-05-29)
|
||||
- uCharts.js 增加条状图type="bar"
|
||||
- 示例项目 pages/ucharts/ucharts.vue增加条状图的demo
|
||||
## 2.1.7-20210524(2021-05-24)
|
||||
- uCharts.js 修复大数据量模式下曲线图不平滑的bug
|
||||
## 2.1.6-20210523(2021-05-23)
|
||||
- 秋云图表组件 修复小程序端开启滚动条更新数据后滚动条位置不符合预期的bug
|
||||
## 2.1.5-2021051702(2021-05-17)
|
||||
- uCharts.js 修复自定义Y轴min和max值为0时不能正确显示的bug
|
||||
## 2.1.5-20210517(2021-05-17)
|
||||
- uCharts.js 修复Y轴自定义min和max时,未按指定的最大值最小值显示坐标轴刻度的bug
|
||||
## 2.1.4-20210516(2021-05-16)
|
||||
- 秋云图表组件 优化onWindowResize防抖方法
|
||||
- 秋云图表组件 修复APP端uCharts更新数据时,清空series显示loading图标后再显示图表,图表抖动的bug
|
||||
- uCharts.js 修复开启canvas2d后,x轴、y轴、series自定义字体大小未按比例缩放的bug
|
||||
- 示例项目 修复format-e.vue拼写错误导致app端使用uCharts渲染图表
|
||||
## 2.1.3-20210513(2021-05-13)
|
||||
- 秋云图表组件 修改uCharts变更chartData数据为updateData方法,支持带滚动条的数据动态打点
|
||||
- 秋云图表组件 增加onWindowResize防抖方法 fix by ど誓言,如尘般染指流年づ
|
||||
- 秋云图表组件 H5或者APP变更chartData数据显示loading图表时,原数据闪现的bug
|
||||
- 秋云图表组件 props增加errorReload禁用错误点击重新加载的方法
|
||||
- uCharts.js 增加tooltip显示category(x轴对应点位)标题的功能,opts.extra.tooltip.showCategory,默认为false
|
||||
- uCharts.js 修复mix混合图只有柱状图时,tooltip的分割线显示位置不正确的bug
|
||||
- uCharts.js 修复开启滚动条,图表在拖动中动态打点,滚动条位置不正确的bug
|
||||
- uCharts.js 修复饼图类数据格式为echarts数据格式,series为空数组报错的bug
|
||||
- 示例项目 修改uCharts.js更新到v2.1.2版本后,@getIndex方法获取索引值变更为e.currentIndex.index
|
||||
- 示例项目 pages/updata/updata.vue增加滚动条拖动更新(数据动态打点)的demo
|
||||
- 示例项目 pages/other/other.vue增加errorReload禁用错误点击重新加载的demo
|
||||
## 2.1.2-20210509(2021-05-09)
|
||||
秋云图表组件 修复APP端初始化时就传入chartData或lacaldata不显示图表的bug
|
||||
## 2.1.1-20210509(2021-05-09)
|
||||
- 秋云图表组件 变更ECharts的eopts配置在renderjs内执行,支持在config-echarts.js配置文件内写function配置。
|
||||
- 秋云图表组件 修复APP端报错Prop being mutated: "onmouse"错误的bug。
|
||||
- 秋云图表组件 修复APP端报错Error: Not Found:Page[6][-1,27] at view.umd.min.js:1的bug。
|
||||
## 2.1.0-20210507(2021-05-07)
|
||||
- 秋云图表组件 修复初始化时就有数据或者数据更新的时候loading加载动画闪动的bug
|
||||
- uCharts.js 修复x轴format方法categories为字符串类型时返回NaN的bug
|
||||
- uCharts.js 修复series.textColor、legend.fontColor未执行全局默认颜色的bug
|
||||
## 2.1.0-20210506(2021-05-06)
|
||||
- 秋云图表组件 修复极个别情况下报错item.properties undefined的bug
|
||||
- 秋云图表组件 修复极个别情况下关闭加载动画reshow不起作用,无法显示图表的bug
|
||||
- 示例项目 pages/ucharts/ucharts.vue 增加时间轴折线图(type="tline")、时间轴区域图(type="tarea")、散点图(type="scatter")、气泡图demo(type="bubble")、倒三角形漏斗图(opts.extra.funnel.type="triangle")、金字塔形漏斗图(opts.extra.funnel.type="pyramid")
|
||||
- 示例项目 pages/format-u/format-u.vue 增加X轴format格式化示例
|
||||
- uCharts.js 升级至v2.1.0版本
|
||||
- uCharts.js 修复 玫瑰图面积模式点击tooltip位置不正确的bug
|
||||
- uCharts.js 修复 玫瑰图点击图例,只剩一个类别显示空白的bug
|
||||
- uCharts.js 修复 饼图类图点击图例,其他图表tooltip位置某些情况下不准的bug
|
||||
- uCharts.js 修复 x轴为矢量轴(时间轴)情况下,点击tooltip位置不正确的bug
|
||||
- uCharts.js 修复 词云图获取点击索引偶尔不准的bug
|
||||
- uCharts.js 增加 直角坐标系图表X轴format格式化方法(原生uCharts.js用法请使用formatter)
|
||||
- uCharts.js 增加 漏斗图扩展配置,倒三角形(opts.extra.funnel.type="triangle"),金字塔形(opts.extra.funnel.type="pyramid")
|
||||
- uCharts.js 增加 散点图(opts.type="scatter")、气泡图(opts.type="bubble")
|
||||
- 后期计划 完善散点图、气泡图,增加markPoints标记点,增加横向条状图。
|
||||
## 2.0.0-20210502(2021-05-02)
|
||||
- uCharts.js 修复词云图获取点击索引不正确的bug
|
||||
## 2.0.0-20210501(2021-05-01)
|
||||
- 秋云图表组件 修复QQ小程序、百度小程序在关闭动画效果情况下,v-for循环使用图表,显示不正确的bug
|
||||
## 2.0.0-20210426(2021-04-26)
|
||||
- 秋云图表组件 修复QQ小程序不支持canvas2d的bug
|
||||
- 秋云图表组件 修复钉钉小程序某些情况点击坐标计算错误的bug
|
||||
- uCharts.js 增加 extra.column.categoryGap 参数,柱状图类每个category点位(X轴点)柱子组之间的间距
|
||||
- uCharts.js 增加 yAxis.data[i].titleOffsetY 参数,标题纵向偏移距离,负数为向上偏移,正数向下偏移
|
||||
- uCharts.js 增加 yAxis.data[i].titleOffsetX 参数,标题横向偏移距离,负数为向左偏移,正数向右偏移
|
||||
- uCharts.js 增加 extra.gauge.labelOffset 参数,仪表盘标签文字径向便宜距离,默认13px
|
||||
## 2.0.0-20210422-2(2021-04-22)
|
||||
秋云图表组件 修复 formatterAssign 未判断 args[key] == null 的情况导致栈溢出的 bug
|
||||
## 2.0.0-20210422(2021-04-22)
|
||||
- 秋云图表组件 修复H5、APP、支付宝小程序、微信小程序canvas2d模式下横屏模式的bug
|
||||
## 2.0.0-20210421(2021-04-21)
|
||||
- uCharts.js 修复多行图例的情况下,图例在上方或者下方时,图例float为左侧或者右侧时,第二行及以后的图例对齐方式不正确的bug
|
||||
## 2.0.0-20210420(2021-04-20)
|
||||
- 秋云图表组件 修复微信小程序开启canvas2d模式后,windows版微信小程序不支持canvas2d模式的bug
|
||||
- 秋云图表组件 修改非uni_modules版本为v2.0版本qiun-data-charts组件
|
||||
## 2.0.0-20210419(2021-04-19)
|
||||
## v1.0版本已停更,建议转uni_modules版本组件方式调用,点击右侧绿色【使用HBuilderX导入插件】即可使用,示例项目请点击右侧蓝色按钮【使用HBuilderX导入示例项目】。
|
||||
## 初次使用如果提示未注册<qiun-data-charts>组件,请重启HBuilderX,如仍不好用,请重启电脑;
|
||||
## 如果是cli项目,请尝试清理node_modules,重新install,还不行就删除项目,再重新install。
|
||||
## 此问题已于DCloud官方确认,HBuilderX下个版本会修复。
|
||||
## 其他图表不显示问题详见[常见问题选项卡](https://demo.ucharts.cn)
|
||||
## <font color=#FF0000> 新手请先完整阅读帮助文档及常见问题3遍,右侧蓝色按钮示例项目请看2遍! </font>
|
||||
## [DEMO演示及在线生成工具(v2.0文档)https://demo.ucharts.cn](https://demo.ucharts.cn)
|
||||
## [图表组件在项目中的应用参见 UReport数据报表](https://ext.dcloud.net.cn/plugin?id=4651)
|
||||
- uCharts.js 修复混合图中柱状图单独设置颜色不生效的bug
|
||||
- uCharts.js 修复多Y轴单独设置fontSize时,开启canvas2d后,未对应放大字体的bug
|
||||
## 2.0.0-20210418(2021-04-18)
|
||||
- 秋云图表组件 增加directory配置,修复H5端history模式下如果发布到二级目录无法正确加载echarts.min.js的bug
|
||||
## 2.0.0-20210416(2021-04-16)
|
||||
## v1.0版本已停更,建议转uni_modules版本组件方式调用,点击右侧绿色【使用HBuilderX导入插件】即可使用,示例项目请点击右侧蓝色按钮【使用HBuilderX导入示例项目】。
|
||||
## 初次使用如果提示未注册<qiun-data-charts>组件,请重启HBuilderX,如仍不好用,请重启电脑;
|
||||
## 如果是cli项目,请尝试清理node_modules,重新install,还不行就删除项目,再重新install。
|
||||
## 此问题已于DCloud官方确认,HBuilderX下个版本会修复。
|
||||
## 其他图表不显示问题详见[常见问题选项卡](https://demo.ucharts.cn)
|
||||
## <font color=#FF0000> 新手请先完整阅读帮助文档及常见问题3遍,右侧蓝色按钮示例项目请看2遍! </font>
|
||||
## [DEMO演示及在线生成工具(v2.0文档)https://demo.ucharts.cn](https://demo.ucharts.cn)
|
||||
## [图表组件在项目中的应用参见 UReport数据报表](https://ext.dcloud.net.cn/plugin?id=4651)
|
||||
- 秋云图表组件 修复APP端某些情况下报错`Not Found Page`的bug,fix by 高级bug开发技术员
|
||||
- 示例项目 修复APP端v-for循环某些情况下报错`Not Found Page`的bug,fix by 高级bug开发技术员
|
||||
- uCharts.js 修复非直角坐标系tooltip提示窗右侧超出未变换方向显示的bug
|
||||
## 2.0.0-20210415(2021-04-15)
|
||||
- 秋云图表组件 修复H5端发布到二级目录下echarts无法加载的bug
|
||||
- 秋云图表组件 修复某些情况下echarts.off('finished')移除监听事件报错的bug
|
||||
## 2.0.0-20210414(2021-04-14)
|
||||
## v1.0版本已停更,建议转uni_modules版本组件方式调用,点击右侧绿色【使用HBuilderX导入插件】即可使用,示例项目请点击右侧蓝色按钮【使用HBuilderX导入示例项目】。
|
||||
## 初次使用如果提示未注册<qiun-data-charts>组件,请重启HBuilderX,如仍不好用,请重启电脑;
|
||||
## 如果是cli项目,请尝试清理node_modules,重新install,还不行就删除项目,再重新install。
|
||||
## 此问题已于DCloud官方确认,HBuilderX下个版本会修复。
|
||||
## 其他图表不显示问题详见[常见问题选项卡](https://demo.ucharts.cn)
|
||||
## <font color=#FF0000> 新手请先完整阅读帮助文档及常见问题3遍,右侧蓝色按钮示例项目请看2遍! </font>
|
||||
## [DEMO演示及在线生成工具(v2.0文档)https://demo.ucharts.cn](https://demo.ucharts.cn)
|
||||
## [图表组件在项目中的应用参见 UReport数据报表](https://ext.dcloud.net.cn/plugin?id=4651)
|
||||
- 秋云图表组件 修复H5端在cli项目下ECharts引用地址错误的bug
|
||||
- 示例项目 增加ECharts的formatter用法的示例(详见示例项目format-e.vue)
|
||||
- uCharts.js 增加圆环图中心背景色的配置extra.ring.centerColor
|
||||
- uCharts.js 修复微信小程序安卓端柱状图开启透明色后显示不正确的bug
|
||||
## 2.0.0-20210413(2021-04-13)
|
||||
- 秋云图表组件 修复百度小程序多个图表真机未能正确获取根元素dom尺寸的bug
|
||||
- 秋云图表组件 修复百度小程序横屏模式方向不正确的bug
|
||||
- 秋云图表组件 修改ontouch时,@getTouchStart@getTouchMove@getTouchEnd的触发条件
|
||||
- uCharts.js 修复饼图类数据格式series属性不生效的bug
|
||||
- uCharts.js 增加时序区域图 详见示例项目中ucharts.vue
|
||||
## 2.0.0-20210412-2(2021-04-12)
|
||||
## v1.0版本已停更,建议转uni_modules版本组件方式调用,点击右侧绿色【使用HBuilderX导入插件】即可使用,示例项目请点击右侧蓝色按钮【使用HBuilderX导入示例项目】。
|
||||
## 初次使用如果提示未注册<qiun-data-charts>组件,请重启HBuilderX。如仍不好用,请重启电脑,此问题已于DCloud官方确认,HBuilderX下个版本会修复。
|
||||
## [DEMO演示及在线生成工具(v2.0文档)https://demo.ucharts.cn](https://demo.ucharts.cn)
|
||||
## [图表组件在uniCloudAdmin中的应用 UReport数据报表](https://ext.dcloud.net.cn/plugin?id=4651)
|
||||
- 秋云图表组件 修复uCharts在APP端横屏模式下不能正确渲染的bug
|
||||
- 示例项目 增加ECharts柱状图渐变色、圆角柱状图、横向柱状图(条状图)的示例
|
||||
## 2.0.0-20210412(2021-04-12)
|
||||
- 秋云图表组件 修复created中判断echarts导致APP端无法识别,改回mounted中判断echarts初始化
|
||||
- uCharts.js 修复2d模式下series.textOffset未乘像素比的bug
|
||||
## 2.0.0-20210411(2021-04-11)
|
||||
## v1.0版本已停更,建议转uni_modules版本组件方式调用,点击右侧绿色【使用HBuilderX导入插件】即可使用,示例项目请点击右侧蓝色按钮【使用HBuilderX导入示例项目】。
|
||||
## 初次使用如果提示未注册<qiun-data-charts>组件,请重启HBuilderX,并清空小程序开发者工具缓存。
|
||||
## [DEMO演示及在线生成工具(v2.0文档)https://demo.ucharts.cn](https://demo.ucharts.cn)
|
||||
## [图表组件在uniCloudAdmin中的应用 UReport数据报表](https://ext.dcloud.net.cn/plugin?id=4651)
|
||||
- uCharts.js 折线图区域图增加connectNulls断点续连的功能,详见示例项目中ucharts.vue
|
||||
- 秋云图表组件 变更初始化方法为created,变更type2d默认值为true,优化2d模式下组件初始化后dom获取不到的bug
|
||||
- 秋云图表组件 修复左右布局时,右侧图表点击坐标错误的bug,修复tooltip柱状图自定义颜色显示object的bug
|
||||
## 2.0.0-20210410(2021-04-10)
|
||||
- 修复左右布局时,右侧图表点击坐标错误的bug,修复柱状图自定义颜色tooltip显示object的bug
|
||||
- 增加标记线及柱状图自定义颜色的demo
|
||||
## 2.0.0-20210409(2021-04-08)
|
||||
## v1.0版本已停更,建议转uni_modules版本组件方式调用,点击右侧【使用HBuilderX导入插件】即可体验,DEMO演示及在线生成工具(v2.0文档)[https://demo.ucharts.cn](https://demo.ucharts.cn)
|
||||
## 图表组件在uniCloudAdmin中的应用 [UReport数据报表](https://ext.dcloud.net.cn/plugin?id=4651)
|
||||
- uCharts.js 修复钉钉小程序百度小程序measureText不准确的bug,修复2d模式下饼图类activeRadius为按比例放大的bug
|
||||
- 修复组件在支付宝小程序端点击位置不准确的bug
|
||||
## 2.0.0-20210408(2021-04-07)
|
||||
- 修复组件在支付宝小程序端不能显示的bug(目前支付宝小程不能点击交互,后续修复)
|
||||
- uCharts.js 修复高分屏下柱状图类,圆弧进度条 自定义宽度不能按比例放大的bug
|
||||
## 2.0.0-20210407(2021-04-06)
|
||||
## v1.0版本已停更,建议转uni_modules版本组件方式调用,点击右侧【使用HBuilderX导入插件】即可体验,DEMO演示及在线生成工具(v2.0文档)[https://demo.ucharts.cn](https://demo.ucharts.cn)
|
||||
## 增加 通过tofix和unit快速格式化y轴的demo add by `howcode`
|
||||
## 增加 图表组件在uniCloudAdmin中的应用 [UReport数据报表](https://ext.dcloud.net.cn/plugin?id=4651)
|
||||
## 2.0.0-20210406(2021-04-05)
|
||||
# 秋云图表组件+uCharts v2.0版本同步上线,使用方法详见https://demo.ucharts.cn帮助页
|
||||
## 2.0.0(2021-04-05)
|
||||
# 秋云图表组件+uCharts v2.0版本同步上线,使用方法详见https://demo.ucharts.cn帮助页
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@ -0,0 +1,162 @@
|
||||
<template>
|
||||
<view class="container loading1">
|
||||
<view class="shape shape1"></view>
|
||||
<view class="shape shape2"></view>
|
||||
<view class="shape shape3"></view>
|
||||
<view class="shape shape4"></view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'loading1',
|
||||
data() {
|
||||
return {
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped="true">
|
||||
.container {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
position: relative;
|
||||
}
|
||||
.container.loading1 {
|
||||
-webkit-transform: rotate(45deg);
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.container .shape {
|
||||
position: absolute;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 1px;
|
||||
}
|
||||
.container .shape.shape1 {
|
||||
left: 0;
|
||||
background-color: #1890FF;
|
||||
}
|
||||
.container .shape.shape2 {
|
||||
right: 0;
|
||||
background-color: #91CB74;
|
||||
}
|
||||
.container .shape.shape3 {
|
||||
bottom: 0;
|
||||
background-color: #FAC858;
|
||||
}
|
||||
.container .shape.shape4 {
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
background-color: #EE6666;
|
||||
}
|
||||
|
||||
.loading1 .shape1 {
|
||||
-webkit-animation: animation1shape1 0.5s ease 0s infinite alternate;
|
||||
animation: animation1shape1 0.5s ease 0s infinite alternate;
|
||||
}
|
||||
|
||||
@-webkit-keyframes animation1shape1 {
|
||||
from {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: translate(16px, 16px);
|
||||
transform: translate(16px, 16px);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes animation1shape1 {
|
||||
from {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: translate(16px, 16px);
|
||||
transform: translate(16px, 16px);
|
||||
}
|
||||
}
|
||||
.loading1 .shape2 {
|
||||
-webkit-animation: animation1shape2 0.5s ease 0s infinite alternate;
|
||||
animation: animation1shape2 0.5s ease 0s infinite alternate;
|
||||
}
|
||||
|
||||
@-webkit-keyframes animation1shape2 {
|
||||
from {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: translate(-16px, 16px);
|
||||
transform: translate(-16px, 16px);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes animation1shape2 {
|
||||
from {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: translate(-16px, 16px);
|
||||
transform: translate(-16px, 16px);
|
||||
}
|
||||
}
|
||||
.loading1 .shape3 {
|
||||
-webkit-animation: animation1shape3 0.5s ease 0s infinite alternate;
|
||||
animation: animation1shape3 0.5s ease 0s infinite alternate;
|
||||
}
|
||||
|
||||
@-webkit-keyframes animation1shape3 {
|
||||
from {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: translate(16px, -16px);
|
||||
transform: translate(16px, -16px);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes animation1shape3 {
|
||||
from {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: translate(16px, -16px);
|
||||
transform: translate(16px, -16px);
|
||||
}
|
||||
}
|
||||
.loading1 .shape4 {
|
||||
-webkit-animation: animation1shape4 0.5s ease 0s infinite alternate;
|
||||
animation: animation1shape4 0.5s ease 0s infinite alternate;
|
||||
}
|
||||
|
||||
@-webkit-keyframes animation1shape4 {
|
||||
from {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: translate(-16px, -16px);
|
||||
transform: translate(-16px, -16px);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes animation1shape4 {
|
||||
from {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: translate(-16px, -16px);
|
||||
transform: translate(-16px, -16px);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</style>
|
@ -0,0 +1,170 @@
|
||||
<template>
|
||||
<view class="container loading2">
|
||||
<view class="shape shape1"></view>
|
||||
<view class="shape shape2"></view>
|
||||
<view class="shape shape3"></view>
|
||||
<view class="shape shape4"></view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'loading2',
|
||||
data() {
|
||||
return {
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped="true">
|
||||
.container {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.container.loading2 {
|
||||
-webkit-transform: rotate(10deg);
|
||||
transform: rotate(10deg);
|
||||
}
|
||||
.container.loading2 .shape {
|
||||
border-radius: 5px;
|
||||
}
|
||||
.container.loading2{
|
||||
-webkit-animation: rotation 1s infinite;
|
||||
animation: rotation 1s infinite;
|
||||
}
|
||||
|
||||
.container .shape {
|
||||
position: absolute;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 1px;
|
||||
}
|
||||
.container .shape.shape1 {
|
||||
left: 0;
|
||||
background-color: #1890FF;
|
||||
}
|
||||
.container .shape.shape2 {
|
||||
right: 0;
|
||||
background-color: #91CB74;
|
||||
}
|
||||
.container .shape.shape3 {
|
||||
bottom: 0;
|
||||
background-color: #FAC858;
|
||||
}
|
||||
.container .shape.shape4 {
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
background-color: #EE6666;
|
||||
}
|
||||
|
||||
|
||||
.loading2 .shape1 {
|
||||
-webkit-animation: animation2shape1 0.5s ease 0s infinite alternate;
|
||||
animation: animation2shape1 0.5s ease 0s infinite alternate;
|
||||
}
|
||||
|
||||
@-webkit-keyframes animation2shape1 {
|
||||
from {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: translate(20px, 20px);
|
||||
transform: translate(20px, 20px);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes animation2shape1 {
|
||||
from {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: translate(20px, 20px);
|
||||
transform: translate(20px, 20px);
|
||||
}
|
||||
}
|
||||
.loading2 .shape2 {
|
||||
-webkit-animation: animation2shape2 0.5s ease 0s infinite alternate;
|
||||
animation: animation2shape2 0.5s ease 0s infinite alternate;
|
||||
}
|
||||
|
||||
@-webkit-keyframes animation2shape2 {
|
||||
from {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: translate(-20px, 20px);
|
||||
transform: translate(-20px, 20px);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes animation2shape2 {
|
||||
from {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: translate(-20px, 20px);
|
||||
transform: translate(-20px, 20px);
|
||||
}
|
||||
}
|
||||
.loading2 .shape3 {
|
||||
-webkit-animation: animation2shape3 0.5s ease 0s infinite alternate;
|
||||
animation: animation2shape3 0.5s ease 0s infinite alternate;
|
||||
}
|
||||
|
||||
@-webkit-keyframes animation2shape3 {
|
||||
from {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: translate(20px, -20px);
|
||||
transform: translate(20px, -20px);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes animation2shape3 {
|
||||
from {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: translate(20px, -20px);
|
||||
transform: translate(20px, -20px);
|
||||
}
|
||||
}
|
||||
.loading2 .shape4 {
|
||||
-webkit-animation: animation2shape4 0.5s ease 0s infinite alternate;
|
||||
animation: animation2shape4 0.5s ease 0s infinite alternate;
|
||||
}
|
||||
|
||||
@-webkit-keyframes animation2shape4 {
|
||||
from {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: translate(-20px, -20px);
|
||||
transform: translate(-20px, -20px);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes animation2shape4 {
|
||||
from {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: translate(-20px, -20px);
|
||||
transform: translate(-20px, -20px);
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
@ -0,0 +1,173 @@
|
||||
<template>
|
||||
<view class="container loading3">
|
||||
<view class="shape shape1"></view>
|
||||
<view class="shape shape2"></view>
|
||||
<view class="shape shape3"></view>
|
||||
<view class="shape shape4"></view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'loading3',
|
||||
data() {
|
||||
return {
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped="true">
|
||||
.container {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.container.loading3 {
|
||||
-webkit-animation: rotation 1s infinite;
|
||||
animation: rotation 1s infinite;
|
||||
}
|
||||
.container.loading3 .shape1 {
|
||||
border-top-left-radius: 10px;
|
||||
}
|
||||
.container.loading3 .shape2 {
|
||||
border-top-right-radius: 10px;
|
||||
}
|
||||
.container.loading3 .shape3 {
|
||||
border-bottom-left-radius: 10px;
|
||||
}
|
||||
.container.loading3 .shape4 {
|
||||
border-bottom-right-radius: 10px;
|
||||
}
|
||||
|
||||
.container .shape {
|
||||
position: absolute;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 1px;
|
||||
}
|
||||
.container .shape.shape1 {
|
||||
left: 0;
|
||||
background-color: #1890FF;
|
||||
}
|
||||
.container .shape.shape2 {
|
||||
right: 0;
|
||||
background-color: #91CB74;
|
||||
}
|
||||
.container .shape.shape3 {
|
||||
bottom: 0;
|
||||
background-color: #FAC858;
|
||||
}
|
||||
.container .shape.shape4 {
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
background-color: #EE6666;
|
||||
}
|
||||
|
||||
.loading3 .shape1 {
|
||||
-webkit-animation: animation3shape1 0.5s ease 0s infinite alternate;
|
||||
animation: animation3shape1 0.5s ease 0s infinite alternate;
|
||||
}
|
||||
|
||||
@-webkit-keyframes animation3shape1 {
|
||||
from {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: translate(5px, 5px);
|
||||
transform: translate(5px, 5px);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes animation3shape1 {
|
||||
from {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: translate(5px, 5px);
|
||||
transform: translate(5px, 5px);
|
||||
}
|
||||
}
|
||||
.loading3 .shape2 {
|
||||
-webkit-animation: animation3shape2 0.5s ease 0s infinite alternate;
|
||||
animation: animation3shape2 0.5s ease 0s infinite alternate;
|
||||
}
|
||||
|
||||
@-webkit-keyframes animation3shape2 {
|
||||
from {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: translate(-5px, 5px);
|
||||
transform: translate(-5px, 5px);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes animation3shape2 {
|
||||
from {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: translate(-5px, 5px);
|
||||
transform: translate(-5px, 5px);
|
||||
}
|
||||
}
|
||||
.loading3 .shape3 {
|
||||
-webkit-animation: animation3shape3 0.5s ease 0s infinite alternate;
|
||||
animation: animation3shape3 0.5s ease 0s infinite alternate;
|
||||
}
|
||||
|
||||
@-webkit-keyframes animation3shape3 {
|
||||
from {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: translate(5px, -5px);
|
||||
transform: translate(5px, -5px);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes animation3shape3 {
|
||||
from {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: translate(5px, -5px);
|
||||
transform: translate(5px, -5px);
|
||||
}
|
||||
}
|
||||
.loading3 .shape4 {
|
||||
-webkit-animation: animation3shape4 0.5s ease 0s infinite alternate;
|
||||
animation: animation3shape4 0.5s ease 0s infinite alternate;
|
||||
}
|
||||
|
||||
@-webkit-keyframes animation3shape4 {
|
||||
from {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: translate(-5px, -5px);
|
||||
transform: translate(-5px, -5px);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes animation3shape4 {
|
||||
from {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: translate(-5px, -5px);
|
||||
transform: translate(-5px, -5px);
|
||||
}
|
||||
}
|
||||
</style>
|
@ -0,0 +1,222 @@
|
||||
<template>
|
||||
<view class="container loading5">
|
||||
<view class="shape shape1"></view>
|
||||
<view class="shape shape2"></view>
|
||||
<view class="shape shape3"></view>
|
||||
<view class="shape shape4"></view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'loading5',
|
||||
data() {
|
||||
return {
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped="true">
|
||||
.container {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.container.loading5 .shape {
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
}
|
||||
|
||||
.container .shape {
|
||||
position: absolute;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 1px;
|
||||
}
|
||||
.container .shape.shape1 {
|
||||
left: 0;
|
||||
background-color: #1890FF;
|
||||
}
|
||||
.container .shape.shape2 {
|
||||
right: 0;
|
||||
background-color: #91CB74;
|
||||
}
|
||||
.container .shape.shape3 {
|
||||
bottom: 0;
|
||||
background-color: #FAC858;
|
||||
}
|
||||
.container .shape.shape4 {
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
background-color: #EE6666;
|
||||
}
|
||||
|
||||
.loading5 .shape1 {
|
||||
animation: animation5shape1 2s ease 0s infinite reverse;
|
||||
}
|
||||
|
||||
@-webkit-keyframes animation5shape1 {
|
||||
0% {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
25% {
|
||||
-webkit-transform: translate(0, 15px);
|
||||
transform: translate(0, 15px);
|
||||
}
|
||||
50% {
|
||||
-webkit-transform: translate(15px, 15px);
|
||||
transform: translate(15px, 15px);
|
||||
}
|
||||
75% {
|
||||
-webkit-transform: translate(15px, 0);
|
||||
transform: translate(15px, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes animation5shape1 {
|
||||
0% {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
25% {
|
||||
-webkit-transform: translate(0, 15px);
|
||||
transform: translate(0, 15px);
|
||||
}
|
||||
50% {
|
||||
-webkit-transform: translate(15px, 15px);
|
||||
transform: translate(15px, 15px);
|
||||
}
|
||||
75% {
|
||||
-webkit-transform: translate(15px, 0);
|
||||
transform: translate(15px, 0);
|
||||
}
|
||||
}
|
||||
.loading5 .shape2 {
|
||||
animation: animation5shape2 2s ease 0s infinite reverse;
|
||||
}
|
||||
|
||||
@-webkit-keyframes animation5shape2 {
|
||||
0% {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
25% {
|
||||
-webkit-transform: translate(-15px, 0);
|
||||
transform: translate(-15px, 0);
|
||||
}
|
||||
50% {
|
||||
-webkit-transform: translate(-15px, 15px);
|
||||
transform: translate(-15px, 15px);
|
||||
}
|
||||
75% {
|
||||
-webkit-transform: translate(0, 15px);
|
||||
transform: translate(0, 15px);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes animation5shape2 {
|
||||
0% {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
25% {
|
||||
-webkit-transform: translate(-15px, 0);
|
||||
transform: translate(-15px, 0);
|
||||
}
|
||||
50% {
|
||||
-webkit-transform: translate(-15px, 15px);
|
||||
transform: translate(-15px, 15px);
|
||||
}
|
||||
75% {
|
||||
-webkit-transform: translate(0, 15px);
|
||||
transform: translate(0, 15px);
|
||||
}
|
||||
}
|
||||
.loading5 .shape3 {
|
||||
animation: animation5shape3 2s ease 0s infinite reverse;
|
||||
}
|
||||
|
||||
@-webkit-keyframes animation5shape3 {
|
||||
0% {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
25% {
|
||||
-webkit-transform: translate(15px, 0);
|
||||
transform: translate(15px, 0);
|
||||
}
|
||||
50% {
|
||||
-webkit-transform: translate(15px, -15px);
|
||||
transform: translate(15px, -15px);
|
||||
}
|
||||
75% {
|
||||
-webkit-transform: translate(0, -15px);
|
||||
transform: translate(0, -15px);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes animation5shape3 {
|
||||
0% {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
25% {
|
||||
-webkit-transform: translate(15px, 0);
|
||||
transform: translate(15px, 0);
|
||||
}
|
||||
50% {
|
||||
-webkit-transform: translate(15px, -15px);
|
||||
transform: translate(15px, -15px);
|
||||
}
|
||||
75% {
|
||||
-webkit-transform: translate(0, -15px);
|
||||
transform: translate(0, -15px);
|
||||
}
|
||||
}
|
||||
.loading5 .shape4 {
|
||||
animation: animation5shape4 2s ease 0s infinite reverse;
|
||||
}
|
||||
|
||||
@-webkit-keyframes animation5shape4 {
|
||||
0% {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
25% {
|
||||
-webkit-transform: translate(0, -15px);
|
||||
transform: translate(0, -15px);
|
||||
}
|
||||
50% {
|
||||
-webkit-transform: translate(-15px, -15px);
|
||||
transform: translate(-15px, -15px);
|
||||
}
|
||||
75% {
|
||||
-webkit-transform: translate(-15px, 0);
|
||||
transform: translate(-15px, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes animation5shape4 {
|
||||
0% {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
25% {
|
||||
-webkit-transform: translate(0, -15px);
|
||||
transform: translate(0, -15px);
|
||||
}
|
||||
50% {
|
||||
-webkit-transform: translate(-15px, -15px);
|
||||
transform: translate(-15px, -15px);
|
||||
}
|
||||
75% {
|
||||
-webkit-transform: translate(-15px, 0);
|
||||
transform: translate(-15px, 0);
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
@ -0,0 +1,229 @@
|
||||
<template>
|
||||
<view class="container loading6">
|
||||
<view class="shape shape1"></view>
|
||||
<view class="shape shape2"></view>
|
||||
<view class="shape shape3"></view>
|
||||
<view class="shape shape4"></view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'loading6',
|
||||
data() {
|
||||
return {
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped="true">
|
||||
.container {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.container.loading6 {
|
||||
-webkit-animation: rotation 1s infinite;
|
||||
animation: rotation 1s infinite;
|
||||
}
|
||||
.container.loading6 .shape {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.container .shape {
|
||||
position: absolute;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 1px;
|
||||
}
|
||||
.container .shape.shape1 {
|
||||
left: 0;
|
||||
background-color: #1890FF;
|
||||
}
|
||||
.container .shape.shape2 {
|
||||
right: 0;
|
||||
background-color: #91CB74;
|
||||
}
|
||||
.container .shape.shape3 {
|
||||
bottom: 0;
|
||||
background-color: #FAC858;
|
||||
}
|
||||
.container .shape.shape4 {
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
background-color: #EE6666;
|
||||
}
|
||||
|
||||
|
||||
.loading6 .shape1 {
|
||||
-webkit-animation: animation6shape1 2s linear 0s infinite normal;
|
||||
animation: animation6shape1 2s linear 0s infinite normal;
|
||||
}
|
||||
|
||||
@-webkit-keyframes animation6shape1 {
|
||||
0% {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
25% {
|
||||
-webkit-transform: translate(0, 18px);
|
||||
transform: translate(0, 18px);
|
||||
}
|
||||
50% {
|
||||
-webkit-transform: translate(18px, 18px);
|
||||
transform: translate(18px, 18px);
|
||||
}
|
||||
75% {
|
||||
-webkit-transform: translate(18px, 0);
|
||||
transform: translate(18px, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes animation6shape1 {
|
||||
0% {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
25% {
|
||||
-webkit-transform: translate(0, 18px);
|
||||
transform: translate(0, 18px);
|
||||
}
|
||||
50% {
|
||||
-webkit-transform: translate(18px, 18px);
|
||||
transform: translate(18px, 18px);
|
||||
}
|
||||
75% {
|
||||
-webkit-transform: translate(18px, 0);
|
||||
transform: translate(18px, 0);
|
||||
}
|
||||
}
|
||||
.loading6 .shape2 {
|
||||
-webkit-animation: animation6shape2 2s linear 0s infinite normal;
|
||||
animation: animation6shape2 2s linear 0s infinite normal;
|
||||
}
|
||||
|
||||
@-webkit-keyframes animation6shape2 {
|
||||
0% {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
25% {
|
||||
-webkit-transform: translate(-18px, 0);
|
||||
transform: translate(-18px, 0);
|
||||
}
|
||||
50% {
|
||||
-webkit-transform: translate(-18px, 18px);
|
||||
transform: translate(-18px, 18px);
|
||||
}
|
||||
75% {
|
||||
-webkit-transform: translate(0, 18px);
|
||||
transform: translate(0, 18px);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes animation6shape2 {
|
||||
0% {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
25% {
|
||||
-webkit-transform: translate(-18px, 0);
|
||||
transform: translate(-18px, 0);
|
||||
}
|
||||
50% {
|
||||
-webkit-transform: translate(-18px, 18px);
|
||||
transform: translate(-18px, 18px);
|
||||
}
|
||||
75% {
|
||||
-webkit-transform: translate(0, 18px);
|
||||
transform: translate(0, 18px);
|
||||
}
|
||||
}
|
||||
.loading6 .shape3 {
|
||||
-webkit-animation: animation6shape3 2s linear 0s infinite normal;
|
||||
animation: animation6shape3 2s linear 0s infinite normal;
|
||||
}
|
||||
|
||||
@-webkit-keyframes animation6shape3 {
|
||||
0% {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
25% {
|
||||
-webkit-transform: translate(18px, 0);
|
||||
transform: translate(18px, 0);
|
||||
}
|
||||
50% {
|
||||
-webkit-transform: translate(18px, -18px);
|
||||
transform: translate(18px, -18px);
|
||||
}
|
||||
75% {
|
||||
-webkit-transform: translate(0, -18px);
|
||||
transform: translate(0, -18px);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes animation6shape3 {
|
||||
0% {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
25% {
|
||||
-webkit-transform: translate(18px, 0);
|
||||
transform: translate(18px, 0);
|
||||
}
|
||||
50% {
|
||||
-webkit-transform: translate(18px, -18px);
|
||||
transform: translate(18px, -18px);
|
||||
}
|
||||
75% {
|
||||
-webkit-transform: translate(0, -18px);
|
||||
transform: translate(0, -18px);
|
||||
}
|
||||
}
|
||||
.loading6 .shape4 {
|
||||
-webkit-animation: animation6shape4 2s linear 0s infinite normal;
|
||||
animation: animation6shape4 2s linear 0s infinite normal;
|
||||
}
|
||||
|
||||
@-webkit-keyframes animation6shape4 {
|
||||
0% {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
25% {
|
||||
-webkit-transform: translate(0, -18px);
|
||||
transform: translate(0, -18px);
|
||||
}
|
||||
50% {
|
||||
-webkit-transform: translate(-18px, -18px);
|
||||
transform: translate(-18px, -18px);
|
||||
}
|
||||
75% {
|
||||
-webkit-transform: translate(-18px, 0);
|
||||
transform: translate(-18px, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes animation6shape4 {
|
||||
0% {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
25% {
|
||||
-webkit-transform: translate(0, -18px);
|
||||
transform: translate(0, -18px);
|
||||
}
|
||||
50% {
|
||||
-webkit-transform: translate(-18px, -18px);
|
||||
transform: translate(-18px, -18px);
|
||||
}
|
||||
75% {
|
||||
-webkit-transform: translate(-18px, 0);
|
||||
transform: translate(-18px, 0);
|
||||
}
|
||||
}
|
||||
</style>
|
@ -0,0 +1,36 @@
|
||||
<template>
|
||||
<view>
|
||||
<Loading1 v-if="loadingType==1"/>
|
||||
<Loading2 v-if="loadingType==2"/>
|
||||
<Loading3 v-if="loadingType==3"/>
|
||||
<Loading4 v-if="loadingType==4"/>
|
||||
<Loading5 v-if="loadingType==5"/>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Loading1 from "./loading1.vue";
|
||||
import Loading2 from "./loading2.vue";
|
||||
import Loading3 from "./loading3.vue";
|
||||
import Loading4 from "./loading4.vue";
|
||||
import Loading5 from "./loading5.vue";
|
||||
export default {
|
||||
components:{Loading1,Loading2,Loading3,Loading4,Loading5},
|
||||
name: 'qiun-loading',
|
||||
props: {
|
||||
loadingType: {
|
||||
type: Number,
|
||||
default: 2
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
};
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
422
uni_modules/qiun-data-charts/js_sdk/u-charts/config-echarts.js
Normal file
422
uni_modules/qiun-data-charts/js_sdk/u-charts/config-echarts.js
Normal file
@ -0,0 +1,422 @@
|
||||
/*
|
||||
* uCharts®
|
||||
* 高性能跨平台图表库,支持H5、APP、小程序(微信/支付宝/百度/头条/QQ/360)、Vue、Taro等支持canvas的框架平台
|
||||
* Copyright (c) 2021 QIUN®秋云 https://www.ucharts.cn All rights reserved.
|
||||
* Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||
* 复制使用请保留本段注释,感谢支持开源!
|
||||
*
|
||||
* uCharts®官方网站
|
||||
* https://www.uCharts.cn
|
||||
*
|
||||
* 开源地址:
|
||||
* https://gitee.com/uCharts/uCharts
|
||||
*
|
||||
* uni-app插件市场地址:
|
||||
* http://ext.dcloud.net.cn/plugin?id=271
|
||||
*
|
||||
*/
|
||||
|
||||
// 通用配置项
|
||||
|
||||
// 主题颜色配置:如每个图表类型需要不同主题,请在对应图表类型上更改color属性
|
||||
const color = ['#1890FF', '#91CB74', '#FAC858', '#EE6666', '#73C0DE', '#3CA272', '#FC8452', '#9A60B4', '#ea7ccc'];
|
||||
|
||||
const cfe = {
|
||||
//demotype为自定义图表类型
|
||||
"type": ["pie", "ring", "rose", "funnel", "line", "column", "area", "radar", "gauge","candle","demotype"],
|
||||
//增加自定义图表类型,如果需要categories,请在这里加入您的图表类型例如最后的"demotype"
|
||||
"categories": ["line", "column", "area", "radar", "gauge", "candle","demotype"],
|
||||
//instance为实例变量承载属性,option为eopts承载属性,不要删除
|
||||
"instance": {},
|
||||
"option": {},
|
||||
//下面是自定义format配置,因除H5端外的其他端无法通过props传递函数,只能通过此属性对应下标的方式来替换
|
||||
"formatter":{
|
||||
"tooltipDemo1":function(res){
|
||||
let result = ''
|
||||
for (let i in res) {
|
||||
if (i == 0) {
|
||||
result += res[i].axisValueLabel + '年销售额'
|
||||
}
|
||||
let value = '--'
|
||||
if (res[i].data !== null) {
|
||||
value = res[i].data
|
||||
}
|
||||
// #ifdef H5
|
||||
result += '\n' + res[i].seriesName + ':' + value + ' 万元'
|
||||
// #endif
|
||||
|
||||
// #ifdef APP-PLUS
|
||||
result += '<br/>' + res[i].marker + res[i].seriesName + ':' + value + ' 万元'
|
||||
// #endif
|
||||
}
|
||||
return result;
|
||||
},
|
||||
legendFormat:function(name){
|
||||
return "自定义图例+"+name;
|
||||
},
|
||||
yAxisFormatDemo:function (value, index) {
|
||||
return value + '元';
|
||||
},
|
||||
seriesFormatDemo:function(res){
|
||||
return res.name + '年' + res.value + '元';
|
||||
}
|
||||
},
|
||||
//这里演示了自定义您的图表类型的option,可以随意命名,之后在组件上 type="demotype" 后,组件会调用这个花括号里的option,如果组件上还存在eopts参数,会将demotype与eopts中option合并后渲染图表。
|
||||
"demotype":{
|
||||
"color": color,
|
||||
//在这里填写echarts的option即可
|
||||
|
||||
},
|
||||
//下面是自定义配置,请添加项目所需的通用配置
|
||||
"column": {
|
||||
"color": color,
|
||||
"title": {
|
||||
"text": ''
|
||||
},
|
||||
"tooltip": {
|
||||
"trigger": 'axis'
|
||||
},
|
||||
"grid": {
|
||||
"top": 30,
|
||||
"bottom": 50,
|
||||
"right": 15,
|
||||
"left": 40
|
||||
},
|
||||
"legend": {
|
||||
"bottom": 'left',
|
||||
},
|
||||
"toolbox": {
|
||||
"show": false,
|
||||
},
|
||||
"xAxis": {
|
||||
"type": 'category',
|
||||
"axisLabel": {
|
||||
"color": '#666666'
|
||||
},
|
||||
"axisLine": {
|
||||
"lineStyle": {
|
||||
"color": '#CCCCCC'
|
||||
}
|
||||
},
|
||||
"boundaryGap": true,
|
||||
"data": []
|
||||
},
|
||||
"yAxis": {
|
||||
"type": 'value',
|
||||
"axisTick": {
|
||||
"show": false,
|
||||
},
|
||||
"axisLabel": {
|
||||
"color": '#666666'
|
||||
},
|
||||
"axisLine": {
|
||||
"lineStyle": {
|
||||
"color": '#CCCCCC'
|
||||
}
|
||||
},
|
||||
},
|
||||
"seriesTemplate": {
|
||||
"name": '',
|
||||
"type": 'bar',
|
||||
"data": [],
|
||||
"barwidth": 20,
|
||||
"label": {
|
||||
"show": true,
|
||||
"color": "#666666",
|
||||
"position": 'top',
|
||||
},
|
||||
},
|
||||
},
|
||||
"line": {
|
||||
"color": color,
|
||||
"title": {
|
||||
"text": ''
|
||||
},
|
||||
"tooltip": {
|
||||
"trigger": 'axis'
|
||||
},
|
||||
"grid": {
|
||||
"top": 30,
|
||||
"bottom": 50,
|
||||
"right": 15,
|
||||
"left": 40
|
||||
},
|
||||
"legend": {
|
||||
"bottom": 'left',
|
||||
},
|
||||
"toolbox": {
|
||||
"show": false,
|
||||
},
|
||||
"xAxis": {
|
||||
"type": 'category',
|
||||
"axisLabel": {
|
||||
"color": '#666666'
|
||||
},
|
||||
"axisLine": {
|
||||
"lineStyle": {
|
||||
"color": '#CCCCCC'
|
||||
}
|
||||
},
|
||||
"boundaryGap": true,
|
||||
"data": []
|
||||
},
|
||||
"yAxis": {
|
||||
"type": 'value',
|
||||
"axisTick": {
|
||||
"show": false,
|
||||
},
|
||||
"axisLabel": {
|
||||
"color": '#666666'
|
||||
},
|
||||
"axisLine": {
|
||||
"lineStyle": {
|
||||
"color": '#CCCCCC'
|
||||
}
|
||||
},
|
||||
},
|
||||
"seriesTemplate": {
|
||||
"name": '',
|
||||
"type": 'line',
|
||||
"data": [],
|
||||
"barwidth": 20,
|
||||
"label": {
|
||||
"show": true,
|
||||
"color": "#666666",
|
||||
"position": 'top',
|
||||
},
|
||||
},
|
||||
},
|
||||
"area": {
|
||||
"color": color,
|
||||
"title": {
|
||||
"text": ''
|
||||
},
|
||||
"tooltip": {
|
||||
"trigger": 'axis'
|
||||
},
|
||||
"grid": {
|
||||
"top": 30,
|
||||
"bottom": 50,
|
||||
"right": 15,
|
||||
"left": 40
|
||||
},
|
||||
"legend": {
|
||||
"bottom": 'left',
|
||||
},
|
||||
"toolbox": {
|
||||
"show": false,
|
||||
},
|
||||
"xAxis": {
|
||||
"type": 'category',
|
||||
"axisLabel": {
|
||||
"color": '#666666'
|
||||
},
|
||||
"axisLine": {
|
||||
"lineStyle": {
|
||||
"color": '#CCCCCC'
|
||||
}
|
||||
},
|
||||
"boundaryGap": true,
|
||||
"data": []
|
||||
},
|
||||
"yAxis": {
|
||||
"type": 'value',
|
||||
"axisTick": {
|
||||
"show": false,
|
||||
},
|
||||
"axisLabel": {
|
||||
"color": '#666666'
|
||||
},
|
||||
"axisLine": {
|
||||
"lineStyle": {
|
||||
"color": '#CCCCCC'
|
||||
}
|
||||
},
|
||||
},
|
||||
"seriesTemplate": {
|
||||
"name": '',
|
||||
"type": 'line',
|
||||
"data": [],
|
||||
"areaStyle": {},
|
||||
"label": {
|
||||
"show": true,
|
||||
"color": "#666666",
|
||||
"position": 'top',
|
||||
},
|
||||
},
|
||||
},
|
||||
"pie": {
|
||||
"color": color,
|
||||
"title": {
|
||||
"text": ''
|
||||
},
|
||||
"tooltip": {
|
||||
"trigger": 'item'
|
||||
},
|
||||
"grid": {
|
||||
"top": 40,
|
||||
"bottom": 30,
|
||||
"right": 15,
|
||||
"left": 15
|
||||
},
|
||||
"legend": {
|
||||
"bottom": 'left',
|
||||
},
|
||||
"seriesTemplate": {
|
||||
"name": '',
|
||||
"type": 'pie',
|
||||
"data": [],
|
||||
"radius": '50%',
|
||||
"label": {
|
||||
"show": true,
|
||||
"color": "#666666",
|
||||
"position": 'top',
|
||||
},
|
||||
},
|
||||
},
|
||||
"ring": {
|
||||
"color": color,
|
||||
"title": {
|
||||
"text": ''
|
||||
},
|
||||
"tooltip": {
|
||||
"trigger": 'item'
|
||||
},
|
||||
"grid": {
|
||||
"top": 40,
|
||||
"bottom": 30,
|
||||
"right": 15,
|
||||
"left": 15
|
||||
},
|
||||
"legend": {
|
||||
"bottom": 'left',
|
||||
},
|
||||
"seriesTemplate": {
|
||||
"name": '',
|
||||
"type": 'pie',
|
||||
"data": [],
|
||||
"radius": ['40%', '70%'],
|
||||
"avoidLabelOverlap": false,
|
||||
"label": {
|
||||
"show": true,
|
||||
"color": "#666666",
|
||||
"position": 'top',
|
||||
},
|
||||
"labelLine": {
|
||||
"show": true
|
||||
},
|
||||
},
|
||||
},
|
||||
"rose": {
|
||||
"color": color,
|
||||
"title": {
|
||||
"text": ''
|
||||
},
|
||||
"tooltip": {
|
||||
"trigger": 'item'
|
||||
},
|
||||
"legend": {
|
||||
"top": 'bottom'
|
||||
},
|
||||
"seriesTemplate": {
|
||||
"name": '',
|
||||
"type": 'pie',
|
||||
"data": [],
|
||||
"radius": "55%",
|
||||
"center": ['50%', '50%'],
|
||||
"roseType": 'area',
|
||||
},
|
||||
},
|
||||
"funnel": {
|
||||
"color": color,
|
||||
"title": {
|
||||
"text": ''
|
||||
},
|
||||
"tooltip": {
|
||||
"trigger": 'item',
|
||||
"formatter": "{b} : {c}%"
|
||||
},
|
||||
"legend": {
|
||||
"top": 'bottom'
|
||||
},
|
||||
"seriesTemplate": {
|
||||
"name": '',
|
||||
"type": 'funnel',
|
||||
"left": '10%',
|
||||
"top": 60,
|
||||
"bottom": 60,
|
||||
"width": '80%',
|
||||
"min": 0,
|
||||
"max": 100,
|
||||
"minSize": '0%',
|
||||
"maxSize": '100%',
|
||||
"sort": 'descending',
|
||||
"gap": 2,
|
||||
"label": {
|
||||
"show": true,
|
||||
"position": 'inside'
|
||||
},
|
||||
"labelLine": {
|
||||
"length": 10,
|
||||
"lineStyle": {
|
||||
"width": 1,
|
||||
"type": 'solid'
|
||||
}
|
||||
},
|
||||
"itemStyle": {
|
||||
"bordercolor": '#fff',
|
||||
"borderwidth": 1
|
||||
},
|
||||
"emphasis": {
|
||||
"label": {
|
||||
"fontSize": 20
|
||||
}
|
||||
},
|
||||
"data": [],
|
||||
},
|
||||
},
|
||||
"gauge": {
|
||||
"color": color,
|
||||
"tooltip": {
|
||||
"formatter": '{a} <br/>{b} : {c}%'
|
||||
},
|
||||
"seriesTemplate": {
|
||||
"name": '业务指标',
|
||||
"type": 'gauge',
|
||||
"detail": {"formatter": '{value}%'},
|
||||
"data": [{"value": 50, "name": '完成率'}]
|
||||
},
|
||||
},
|
||||
"candle": {
|
||||
"xAxis": {
|
||||
"data": []
|
||||
},
|
||||
"yAxis": {},
|
||||
"color": color,
|
||||
"title": {
|
||||
"text": ''
|
||||
},
|
||||
"dataZoom": [{
|
||||
"type": 'inside',
|
||||
"xAxisIndex": [0, 1],
|
||||
"start": 10,
|
||||
"end": 100
|
||||
},
|
||||
{
|
||||
"show": true,
|
||||
"xAxisIndex": [0, 1],
|
||||
"type": 'slider',
|
||||
"bottom": 10,
|
||||
"start": 10,
|
||||
"end": 100
|
||||
}
|
||||
],
|
||||
"seriesTemplate": {
|
||||
"name": '',
|
||||
"type": 'k',
|
||||
"data": [],
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export default cfe;
|
606
uni_modules/qiun-data-charts/js_sdk/u-charts/config-ucharts.js
Normal file
606
uni_modules/qiun-data-charts/js_sdk/u-charts/config-ucharts.js
Normal file
@ -0,0 +1,606 @@
|
||||
/*
|
||||
* uCharts®
|
||||
* 高性能跨平台图表库,支持H5、APP、小程序(微信/支付宝/百度/头条/QQ/360)、Vue、Taro等支持canvas的框架平台
|
||||
* Copyright (c) 2021 QIUN®秋云 https://www.ucharts.cn All rights reserved.
|
||||
* Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||
* 复制使用请保留本段注释,感谢支持开源!
|
||||
*
|
||||
* uCharts®官方网站
|
||||
* https://www.uCharts.cn
|
||||
*
|
||||
* 开源地址:
|
||||
* https://gitee.com/uCharts/uCharts
|
||||
*
|
||||
* uni-app插件市场地址:
|
||||
* http://ext.dcloud.net.cn/plugin?id=271
|
||||
*
|
||||
*/
|
||||
|
||||
// 主题颜色配置:如每个图表类型需要不同主题,请在对应图表类型上更改color属性
|
||||
const color = ['#1890FF', '#91CB74', '#FAC858', '#EE6666', '#73C0DE', '#3CA272', '#FC8452', '#9A60B4', '#ea7ccc'];
|
||||
|
||||
//事件转换函数,主要用作格式化x轴为时间轴,根据需求自行修改
|
||||
const formatDateTime = (timeStamp, returnType)=>{
|
||||
var date = new Date();
|
||||
date.setTime(timeStamp * 1000);
|
||||
var y = date.getFullYear();
|
||||
var m = date.getMonth() + 1;
|
||||
m = m < 10 ? ('0' + m) : m;
|
||||
var d = date.getDate();
|
||||
d = d < 10 ? ('0' + d) : d;
|
||||
var h = date.getHours();
|
||||
h = h < 10 ? ('0' + h) : h;
|
||||
var minute = date.getMinutes();
|
||||
var second = date.getSeconds();
|
||||
minute = minute < 10 ? ('0' + minute) : minute;
|
||||
second = second < 10 ? ('0' + second) : second;
|
||||
if(returnType == 'full'){return y + '-' + m + '-' + d + ' '+ h +':' + minute + ':' + second;}
|
||||
if(returnType == 'y-m-d'){return y + '-' + m + '-' + d;}
|
||||
if(returnType == 'h:m'){return h +':' + minute;}
|
||||
if(returnType == 'h:m:s'){return h +':' + minute +':' + second;}
|
||||
return [y, m, d, h, minute, second];
|
||||
}
|
||||
|
||||
const cfu = {
|
||||
//demotype为自定义图表类型,一般不需要自定义图表类型,只需要改根节点上对应的类型即可
|
||||
"type":["pie","ring","rose","word","funnel","map","arcbar","line","column","mount","bar","area","radar","gauge","candle","mix","tline","tarea","scatter","bubble","demotype"],
|
||||
"range":["饼状图","圆环图","玫瑰图","词云图","漏斗图","地图","圆弧进度条","折线图","柱状图","山峰图","条状图","区域图","雷达图","仪表盘","K线图","混合图","时间轴折线","时间轴区域","散点图","气泡图","自定义类型"],
|
||||
//增加自定义图表类型,如果需要categories,请在这里加入您的图表类型,例如最后的"demotype"
|
||||
//自定义类型时需要注意"tline","tarea","scatter","bubble"等时间轴(矢量x轴)类图表,没有categories,不需要加入categories
|
||||
"categories":["line","column","mount","bar","area","radar","gauge","candle","mix","demotype"],
|
||||
//instance为实例变量承载属性,不要删除
|
||||
"instance":{},
|
||||
//option为opts及eopts承载属性,不要删除
|
||||
"option":{},
|
||||
//下面是自定义format配置,因除H5端外的其他端无法通过props传递函数,只能通过此属性对应下标的方式来替换
|
||||
"formatter":{
|
||||
"yAxisDemo1":function(val, index, opts){return val+'元'},
|
||||
"yAxisDemo2":function(val, index, opts){return val.toFixed(2)},
|
||||
"xAxisDemo1":function(val, index, opts){return val+'年';},
|
||||
"xAxisDemo2":function(val, index, opts){return formatDateTime(val,'h:m')},
|
||||
"seriesDemo1":function(val, index, series, opts){return val+'元'},
|
||||
"tooltipDemo1":function(item, category, index, opts){
|
||||
if(index==0){
|
||||
return '随便用'+item.data+'年'
|
||||
}else{
|
||||
return '其他我没改'+item.data+'天'
|
||||
}
|
||||
},
|
||||
"pieDemo":function(val, index, series, opts){
|
||||
if(index !== undefined){
|
||||
return series[index].name+':'+series[index].data+'元'
|
||||
}
|
||||
},
|
||||
},
|
||||
//这里演示了自定义您的图表类型的option,可以随意命名,之后在组件上 type="demotype" 后,组件会调用这个花括号里的option,如果组件上还存在opts参数,会将demotype与opts中option合并后渲染图表。
|
||||
"demotype":{
|
||||
//我这里把曲线图当做了自定义图表类型,您可以根据需要随意指定类型或配置
|
||||
"type": "line",
|
||||
"color": color,
|
||||
"padding": [15,10,0,15],
|
||||
"xAxis": {
|
||||
"disableGrid": true,
|
||||
},
|
||||
"yAxis": {
|
||||
"gridType": "dash",
|
||||
"dashLength": 2,
|
||||
},
|
||||
"legend": {
|
||||
},
|
||||
"extra": {
|
||||
"line": {
|
||||
"type": "curve",
|
||||
"width": 2
|
||||
},
|
||||
}
|
||||
},
|
||||
//下面是自定义配置,请添加项目所需的通用配置
|
||||
"pie":{
|
||||
"type": "pie",
|
||||
"color": color,
|
||||
"padding": [5,5,5,5],
|
||||
"extra": {
|
||||
"pie": {
|
||||
"activeOpacity": 0.5,
|
||||
"activeRadius": 10,
|
||||
"offsetAngle": 0,
|
||||
"labelWidth": 15,
|
||||
"border": true,
|
||||
"borderWidth": 3,
|
||||
"borderColor": "#FFFFFF"
|
||||
},
|
||||
}
|
||||
},
|
||||
"ring":{
|
||||
"type": "ring",
|
||||
"color": color,
|
||||
"padding": [5,5,5,5],
|
||||
"rotate": false,
|
||||
"dataLabel": true,
|
||||
"legend": {
|
||||
"show": true,
|
||||
"position": "right",
|
||||
"lineHeight": 25,
|
||||
},
|
||||
"title": {
|
||||
"name": "收益率",
|
||||
"fontSize": 15,
|
||||
"color": "#666666"
|
||||
},
|
||||
"subtitle": {
|
||||
"name": "70%",
|
||||
"fontSize": 25,
|
||||
"color": "#7cb5ec"
|
||||
},
|
||||
"extra": {
|
||||
"ring": {
|
||||
"ringWidth":30,
|
||||
"activeOpacity": 0.5,
|
||||
"activeRadius": 10,
|
||||
"offsetAngle": 0,
|
||||
"labelWidth": 15,
|
||||
"border": true,
|
||||
"borderWidth": 3,
|
||||
"borderColor": "#FFFFFF"
|
||||
},
|
||||
},
|
||||
},
|
||||
"rose":{
|
||||
"type": "rose",
|
||||
"color": color,
|
||||
"padding": [5,5,5,5],
|
||||
"legend": {
|
||||
"show": true,
|
||||
"position": "left",
|
||||
"lineHeight": 25,
|
||||
},
|
||||
"extra": {
|
||||
"rose": {
|
||||
"type": "area",
|
||||
"minRadius": 50,
|
||||
"activeOpacity": 0.5,
|
||||
"activeRadius": 10,
|
||||
"offsetAngle": 0,
|
||||
"labelWidth": 15,
|
||||
"border": false,
|
||||
"borderWidth": 2,
|
||||
"borderColor": "#FFFFFF"
|
||||
},
|
||||
}
|
||||
},
|
||||
"word":{
|
||||
"type": "word",
|
||||
"color": color,
|
||||
"extra": {
|
||||
"word": {
|
||||
"type": "normal",
|
||||
"autoColors": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"funnel":{
|
||||
"type": "funnel",
|
||||
"color": color,
|
||||
"padding": [15,15,0,15],
|
||||
"extra": {
|
||||
"funnel": {
|
||||
"activeOpacity": 0.3,
|
||||
"activeWidth": 10,
|
||||
"border": true,
|
||||
"borderWidth": 2,
|
||||
"borderColor": "#FFFFFF",
|
||||
"fillOpacity": 1,
|
||||
"labelAlign": "right"
|
||||
},
|
||||
}
|
||||
},
|
||||
"map":{
|
||||
"type": "map",
|
||||
"color": color,
|
||||
"padding": [0,0,0,0],
|
||||
"dataLabel": true,
|
||||
"extra": {
|
||||
"map": {
|
||||
"border": true,
|
||||
"borderWidth": 1,
|
||||
"borderColor": "#666666",
|
||||
"fillOpacity": 0.6,
|
||||
"activeBorderColor": "#F04864",
|
||||
"activeFillColor": "#FACC14",
|
||||
"activeFillOpacity": 1
|
||||
},
|
||||
}
|
||||
},
|
||||
"arcbar":{
|
||||
"type": "arcbar",
|
||||
"color": color,
|
||||
"title": {
|
||||
"name": "百分比",
|
||||
"fontSize": 25,
|
||||
"color": "#00FF00"
|
||||
},
|
||||
"subtitle": {
|
||||
"name": "默认标题",
|
||||
"fontSize": 15,
|
||||
"color": "#666666"
|
||||
},
|
||||
"extra": {
|
||||
"arcbar": {
|
||||
"type": "default",
|
||||
"width": 12,
|
||||
"backgroundColor": "#E9E9E9",
|
||||
"startAngle": 0.75,
|
||||
"endAngle": 0.25,
|
||||
"gap": 2
|
||||
}
|
||||
}
|
||||
},
|
||||
"line":{
|
||||
"type": "line",
|
||||
"color": color,
|
||||
"padding": [15,10,0,15],
|
||||
"xAxis": {
|
||||
"disableGrid": true,
|
||||
},
|
||||
"yAxis": {
|
||||
"gridType": "dash",
|
||||
"dashLength": 2,
|
||||
},
|
||||
"legend": {
|
||||
},
|
||||
"extra": {
|
||||
"line": {
|
||||
"type": "straight",
|
||||
"width": 2,
|
||||
"activeType": "hollow"
|
||||
},
|
||||
}
|
||||
},
|
||||
"tline":{
|
||||
"type": "line",
|
||||
"color": color,
|
||||
"padding": [15,10,0,15],
|
||||
"xAxis": {
|
||||
"disableGrid": false,
|
||||
"boundaryGap":"justify",
|
||||
},
|
||||
"yAxis": {
|
||||
"gridType": "dash",
|
||||
"dashLength": 2,
|
||||
"data":[
|
||||
{
|
||||
"min":0,
|
||||
"max":80
|
||||
}
|
||||
]
|
||||
},
|
||||
"legend": {
|
||||
},
|
||||
"extra": {
|
||||
"line": {
|
||||
"type": "curve",
|
||||
"width": 2,
|
||||
"activeType": "hollow"
|
||||
},
|
||||
}
|
||||
},
|
||||
"tarea":{
|
||||
"type": "area",
|
||||
"color": color,
|
||||
"padding": [15,10,0,15],
|
||||
"xAxis": {
|
||||
"disableGrid": true,
|
||||
"boundaryGap":"justify",
|
||||
},
|
||||
"yAxis": {
|
||||
"gridType": "dash",
|
||||
"dashLength": 2,
|
||||
"data":[
|
||||
{
|
||||
"min":0,
|
||||
"max":80
|
||||
}
|
||||
]
|
||||
},
|
||||
"legend": {
|
||||
},
|
||||
"extra": {
|
||||
"area": {
|
||||
"type": "curve",
|
||||
"opacity": 0.2,
|
||||
"addLine": true,
|
||||
"width": 2,
|
||||
"gradient": true,
|
||||
"activeType": "hollow"
|
||||
},
|
||||
}
|
||||
},
|
||||
"column":{
|
||||
"type": "column",
|
||||
"color": color,
|
||||
"padding": [15,15,0,5],
|
||||
"xAxis": {
|
||||
"disableGrid": true,
|
||||
},
|
||||
"yAxis": {
|
||||
"data":[{"min":0}]
|
||||
},
|
||||
"legend": {
|
||||
},
|
||||
"extra": {
|
||||
"column": {
|
||||
"type": "group",
|
||||
"width": 30,
|
||||
"activeBgColor": "#000000",
|
||||
"activeBgOpacity": 0.08
|
||||
},
|
||||
}
|
||||
},
|
||||
"mount":{
|
||||
"type": "mount",
|
||||
"color": color,
|
||||
"padding": [15,15,0,5],
|
||||
"xAxis": {
|
||||
"disableGrid": true,
|
||||
},
|
||||
"yAxis": {
|
||||
"data":[{"min":0}]
|
||||
},
|
||||
"legend": {
|
||||
},
|
||||
"extra": {
|
||||
"mount": {
|
||||
"type": "mount",
|
||||
"widthRatio": 1.5,
|
||||
},
|
||||
}
|
||||
},
|
||||
"bar":{
|
||||
"type": "bar",
|
||||
"color": color,
|
||||
"padding": [15,30,0,5],
|
||||
"xAxis": {
|
||||
"boundaryGap":"justify",
|
||||
"disableGrid":false,
|
||||
"min":0,
|
||||
"axisLine":false
|
||||
},
|
||||
"yAxis": {
|
||||
},
|
||||
"legend": {
|
||||
},
|
||||
"extra": {
|
||||
"bar": {
|
||||
"type": "group",
|
||||
"width": 30,
|
||||
"meterBorde": 1,
|
||||
"meterFillColor": "#FFFFFF",
|
||||
"activeBgColor": "#000000",
|
||||
"activeBgOpacity": 0.08
|
||||
},
|
||||
}
|
||||
},
|
||||
"area":{
|
||||
"type": "area",
|
||||
"color": color,
|
||||
"padding": [15,15,0,15],
|
||||
"xAxis": {
|
||||
"disableGrid": true,
|
||||
},
|
||||
"yAxis": {
|
||||
"gridType": "dash",
|
||||
"dashLength": 2,
|
||||
},
|
||||
"legend": {
|
||||
},
|
||||
"extra": {
|
||||
"area": {
|
||||
"type": "straight",
|
||||
"opacity": 0.2,
|
||||
"addLine": true,
|
||||
"width": 2,
|
||||
"gradient": false,
|
||||
"activeType": "hollow"
|
||||
},
|
||||
}
|
||||
},
|
||||
"radar":{
|
||||
"type": "radar",
|
||||
"color": color,
|
||||
"padding": [5,5,5,5],
|
||||
"dataLabel": false,
|
||||
"legend": {
|
||||
"show": true,
|
||||
"position": "right",
|
||||
"lineHeight": 25,
|
||||
},
|
||||
"extra": {
|
||||
"radar": {
|
||||
"gridType": "radar",
|
||||
"gridColor": "#CCCCCC",
|
||||
"gridCount": 3,
|
||||
"opacity": 0.2,
|
||||
"max": 200,
|
||||
"labelShow": true
|
||||
},
|
||||
}
|
||||
},
|
||||
"gauge":{
|
||||
"type": "gauge",
|
||||
"color": color,
|
||||
"title": {
|
||||
"name": "66Km/H",
|
||||
"fontSize": 25,
|
||||
"color": "#2fc25b",
|
||||
"offsetY": 50
|
||||
},
|
||||
"subtitle": {
|
||||
"name": "实时速度",
|
||||
"fontSize": 15,
|
||||
"color": "#1890ff",
|
||||
"offsetY": -50
|
||||
},
|
||||
"extra": {
|
||||
"gauge": {
|
||||
"type": "default",
|
||||
"width": 30,
|
||||
"labelColor": "#666666",
|
||||
"startAngle": 0.75,
|
||||
"endAngle": 0.25,
|
||||
"startNumber": 0,
|
||||
"endNumber": 100,
|
||||
"labelFormat": "",
|
||||
"splitLine": {
|
||||
"fixRadius": 0,
|
||||
"splitNumber": 10,
|
||||
"width": 30,
|
||||
"color": "#FFFFFF",
|
||||
"childNumber": 5,
|
||||
"childWidth": 12
|
||||
},
|
||||
"pointer": {
|
||||
"width": 24,
|
||||
"color": "auto"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"candle":{
|
||||
"type": "candle",
|
||||
"color": color,
|
||||
"padding": [15,15,0,15],
|
||||
"enableScroll": true,
|
||||
"enableMarkLine": true,
|
||||
"dataLabel": false,
|
||||
"xAxis": {
|
||||
"labelCount": 4,
|
||||
"itemCount": 40,
|
||||
"disableGrid": true,
|
||||
"gridColor": "#CCCCCC",
|
||||
"gridType": "solid",
|
||||
"dashLength": 4,
|
||||
"scrollShow": true,
|
||||
"scrollAlign": "left",
|
||||
"scrollColor": "#A6A6A6",
|
||||
"scrollBackgroundColor": "#EFEBEF"
|
||||
},
|
||||
"yAxis": {
|
||||
},
|
||||
"legend": {
|
||||
},
|
||||
"extra": {
|
||||
"candle": {
|
||||
"color": {
|
||||
"upLine": "#f04864",
|
||||
"upFill": "#f04864",
|
||||
"downLine": "#2fc25b",
|
||||
"downFill": "#2fc25b"
|
||||
},
|
||||
"average": {
|
||||
"show": true,
|
||||
"name": ["MA5","MA10","MA30"],
|
||||
"day": [5,10,20],
|
||||
"color": ["#1890ff","#2fc25b","#facc14"]
|
||||
}
|
||||
},
|
||||
"markLine": {
|
||||
"type": "dash",
|
||||
"dashLength": 5,
|
||||
"data": [
|
||||
{
|
||||
"value": 2150,
|
||||
"lineColor": "#f04864",
|
||||
"showLabel": true
|
||||
},
|
||||
{
|
||||
"value": 2350,
|
||||
"lineColor": "#f04864",
|
||||
"showLabel": true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"mix":{
|
||||
"type": "mix",
|
||||
"color": color,
|
||||
"padding": [15,15,0,15],
|
||||
"xAxis": {
|
||||
"disableGrid": true,
|
||||
},
|
||||
"yAxis": {
|
||||
"disabled": false,
|
||||
"disableGrid": false,
|
||||
"splitNumber": 5,
|
||||
"gridType": "dash",
|
||||
"dashLength": 4,
|
||||
"gridColor": "#CCCCCC",
|
||||
"padding": 10,
|
||||
"showTitle": true,
|
||||
"data": []
|
||||
},
|
||||
"legend": {
|
||||
},
|
||||
"extra": {
|
||||
"mix": {
|
||||
"column": {
|
||||
"width": 20
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
"scatter":{
|
||||
"type": "scatter",
|
||||
"color":color,
|
||||
"padding":[15,15,0,15],
|
||||
"dataLabel":false,
|
||||
"xAxis": {
|
||||
"disableGrid": false,
|
||||
"gridType":"dash",
|
||||
"splitNumber":5,
|
||||
"boundaryGap":"justify",
|
||||
"min":0
|
||||
},
|
||||
"yAxis": {
|
||||
"disableGrid": false,
|
||||
"gridType":"dash",
|
||||
},
|
||||
"legend": {
|
||||
},
|
||||
"extra": {
|
||||
"scatter": {
|
||||
},
|
||||
}
|
||||
},
|
||||
"bubble":{
|
||||
"type": "bubble",
|
||||
"color":color,
|
||||
"padding":[15,15,0,15],
|
||||
"xAxis": {
|
||||
"disableGrid": false,
|
||||
"gridType":"dash",
|
||||
"splitNumber":5,
|
||||
"boundaryGap":"justify",
|
||||
"min":0,
|
||||
"max":250
|
||||
},
|
||||
"yAxis": {
|
||||
"disableGrid": false,
|
||||
"gridType":"dash",
|
||||
"data":[{
|
||||
"min":0,
|
||||
"max":150
|
||||
}]
|
||||
},
|
||||
"legend": {
|
||||
},
|
||||
"extra": {
|
||||
"bubble": {
|
||||
"border":2,
|
||||
"opacity": 0.5,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default cfu;
|
5
uni_modules/qiun-data-charts/js_sdk/u-charts/readme.md
Normal file
5
uni_modules/qiun-data-charts/js_sdk/u-charts/readme.md
Normal file
@ -0,0 +1,5 @@
|
||||
# uCharts JSSDK说明
|
||||
1、如不使用uCharts组件,可直接引用u-charts.js,打包编译后会`自动压缩`,压缩后体积约为`120kb`。
|
||||
2、如果120kb的体积仍需压缩,请手到uCharts官网通过在线定制选择您需要的图表。
|
||||
3、config-ucharts.js为uCharts组件的用户配置文件,升级前请`自行备份config-ucharts.js`文件,以免被强制覆盖。
|
||||
4、config-echarts.js为ECharts组件的用户配置文件,升级前请`自行备份config-echarts.js`文件,以免被强制覆盖。
|
7706
uni_modules/qiun-data-charts/js_sdk/u-charts/u-charts.js
Normal file
7706
uni_modules/qiun-data-charts/js_sdk/u-charts/u-charts.js
Normal file
File diff suppressed because it is too large
Load Diff
18
uni_modules/qiun-data-charts/js_sdk/u-charts/u-charts.min.js
vendored
Normal file
18
uni_modules/qiun-data-charts/js_sdk/u-charts/u-charts.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
201
uni_modules/qiun-data-charts/license.md
Normal file
201
uni_modules/qiun-data-charts/license.md
Normal file
@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
80
uni_modules/qiun-data-charts/package.json
Normal file
80
uni_modules/qiun-data-charts/package.json
Normal file
@ -0,0 +1,80 @@
|
||||
{
|
||||
"id": "qiun-data-charts",
|
||||
"displayName": "秋云 ucharts echarts 高性能跨全端图表组件",
|
||||
"version": "2.5.0-20230101",
|
||||
"description": "uCharts 新增正负柱状图!支持H5及APP用 ucharts echarts 渲染图表,uniapp可视化首选组件",
|
||||
"keywords": [
|
||||
"ucharts",
|
||||
"echarts",
|
||||
"f2",
|
||||
"图表",
|
||||
"可视化"
|
||||
],
|
||||
"repository": "https://gitee.com/uCharts/uCharts",
|
||||
"engines": {
|
||||
},
|
||||
"dcloudext": {
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": "474119"
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "插件不采集任何数据",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": "https://www.npmjs.com/~qiun",
|
||||
"type": "component-vue"
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y"
|
||||
},
|
||||
"client": {
|
||||
"App": {
|
||||
"app-vue": "y",
|
||||
"app-nvue": "y"
|
||||
},
|
||||
"H5-mobile": {
|
||||
"Safari": "y",
|
||||
"Android Browser": "y",
|
||||
"微信浏览器(Android)": "y",
|
||||
"QQ浏览器(Android)": "y"
|
||||
},
|
||||
"H5-pc": {
|
||||
"Chrome": "y",
|
||||
"IE": "y",
|
||||
"Edge": "y",
|
||||
"Firefox": "y",
|
||||
"Safari": "y"
|
||||
},
|
||||
"小程序": {
|
||||
"微信": "y",
|
||||
"阿里": "y",
|
||||
"百度": "y",
|
||||
"字节跳动": "y",
|
||||
"QQ": "y"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "y",
|
||||
"联盟": "y"
|
||||
},
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
84
uni_modules/qiun-data-charts/readme.md
Normal file
84
uni_modules/qiun-data-charts/readme.md
Normal file
@ -0,0 +1,84 @@
|
||||

|
||||
|
||||
|
||||
[](https://gitee.com/uCharts/uCharts/stargazers)
|
||||
[](https://gitee.com/uCharts/uCharts/members)
|
||||
[](https://www.apache.org/licenses/LICENSE-2.0.html)
|
||||
[](https://www.npmjs.com/~qiun)
|
||||
|
||||
|
||||
## uCharts简介
|
||||
|
||||
`uCharts`是一款基于`canvas API`开发的适用于所有前端应用的图表库,开发者编写一套代码,可运行到 Web、iOS、Android(基于 uni-app / taro )、以及各种小程序(微信/支付宝/百度/头条/飞书/QQ/快手/钉钉/淘宝)、快应用等更多支持 canvas API 的平台。
|
||||
|
||||
## 官方网站
|
||||
|
||||
## [https://www.ucharts.cn](https://www.ucharts.cn)
|
||||
|
||||
## 快速体验
|
||||
|
||||
一套代码编到多个平台,依次扫描二维码,亲自体验uCharts图表跨平台效果!其他平台请自行编译。
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
## 致开发者
|
||||
|
||||
感谢各位开发者`五年`来对秋云及uCharts的支持,uCharts的进步离不开各位开发者的鼓励与贡献。为更好的帮助各位开发者使用图表工具,我们推出了新版官网,增加了在线定制、问答社区、在线配置等一些增值服务,为确保您能更好的应用图表组件,建议您先`仔细阅读官网指南`以及`常见问题`,而不是下载下来`直接使用`。如仍然不能解决,请到`官网社区`或开通会员后加入`专属VIP会员群`提问将会很快得到回答。
|
||||
|
||||
## 视频教程
|
||||
|
||||
## [uCharts新手入门教程](https://www.bilibili.com/video/BV1qA411Q7se/?share_source=copy_web&vd_source=42a1242f9aaade6427736af69eb2e1d9)
|
||||
|
||||
|
||||
## 社群支持
|
||||
|
||||
uCharts官方拥有5个2000人的QQ群及专属VIP会员群支持,庞大的用户量证明我们一直在努力,请各位放心使用!uCharts的开源图表组件的开发,团队付出了大量的时间与精力,经过四来的考验,不会有比较明显的bug,请各位放心使用。如果您有更好的想法,可以在`码云提交Pull Requests`以帮助更多开发者完成需求,再次感谢各位对uCharts的鼓励与支持!
|
||||
|
||||
#### 官方交流群
|
||||
- 交流群1:371774600(已满)
|
||||
- 交流群2:619841586(已满)
|
||||
- 交流群3:955340127(已满)
|
||||
- 交流群4:641669795(已满)
|
||||
- 交流群5:236294809(只能扫码加入)
|
||||
|
||||

|
||||
|
||||
- 口令`uniapp`
|
||||
|
||||
#### 专属VIP会员群
|
||||
- 开通会员后详见【账号详情】页面中顶部的滚动通知
|
||||
- 口令`您的用户ID`
|
||||
|
||||
## 版权信息
|
||||
|
||||
uCharts始终坚持开源,遵循 [Apache Licence 2.0](https://www.apache.org/licenses/LICENSE-2.0.html) 开源协议,意味着您无需支付任何费用,即可将uCharts应用到您的产品中。
|
||||
|
||||
注意:这并不意味着您可以将uCharts应用到非法的领域,比如涉及赌博,暴力等方面。如因此产生纠纷或法律问题,uCharts相关方及秋云科技不承担任何责任。
|
||||
|
||||
## 合作伙伴
|
||||
|
||||
[](https://www.diygw.com/)
|
||||
[](https://gitee.com/howcode/has-chat)
|
||||
[](https://www.uviewui.com/)
|
||||
[](https://ext.dcloud.net.cn/plugin?id=7088)
|
||||
[](https://ext.dcloud.net.cn/publisher?id=202)
|
||||
[](https://www.firstui.cn/)
|
||||
[](https://ext.dcloud.net.cn/plugin?id=5169)
|
||||
[](https://www.graceui.com/)
|
||||
|
||||
|
||||
## 更新记录
|
||||
|
||||
详见官网指南中说明,[点击此处查看](https://www.ucharts.cn/v2/#/guide/index?id=100)
|
||||
|
||||
|
||||
## 相关链接
|
||||
- [uCharts官网](https://www.ucharts.cn)
|
||||
- [DCloud插件市场地址](https://ext.dcloud.net.cn/plugin?id=271)
|
||||
- [uCharts码云开源托管地址](https://gitee.com/uCharts/uCharts) [](https://gitee.com/uCharts/uCharts/stargazers)
|
||||
- [uCharts npm开源地址](https://www.ucharts.cn)
|
||||
- [ECharts官网](https://echarts.apache.org/zh/index.html)
|
||||
- [ECharts配置手册](https://echarts.apache.org/zh/option.html)
|
||||
- [图表组件在项目中的应用 ReportPlus数据报表](https://www.ucharts.cn/v2/#/layout/info?id=1)
|
23
uni_modules/qiun-data-charts/static/app-plus/echarts.min.js
vendored
Normal file
23
uni_modules/qiun-data-charts/static/app-plus/echarts.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
23
uni_modules/qiun-data-charts/static/h5/echarts.min.js
vendored
Normal file
23
uni_modules/qiun-data-charts/static/h5/echarts.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user