邀请成员、成员列表等

master
yujialong 3 years ago
parent 98bf599434
commit 2e5c25f0b9
  1. 4
      apis/modules/order.js
  2. 10
      apis/modules/parner.js
  3. 19
      apis/request.js
  4. 2
      config/request.js
  5. 4
      libs/util.js
  6. 26
      pages.json
  7. 2
      pages/addStaff/addStaff.vue
  8. 6
      pages/clients/clients.vue
  9. 29
      pages/login/login.vue
  10. 10
      pages/orders/orders.vue
  11. 67
      pages/qrcode/qrcode.vue
  12. 77
      pages/teams/teams.vue
  13. 44
      uni_modules/Sansnn-uQRCode/changelog.md
  14. 241
      uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/bridge/bridge-weex.js
  15. 18
      uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-2d/FillStyleLinearGradient.js
  16. 8
      uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-2d/FillStylePattern.js
  17. 17
      uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-2d/FillStyleRadialGradient.js
  18. 666
      uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-2d/RenderingContext.js
  19. 11
      uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/ActiveInfo.js
  20. 21
      uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/Buffer.js
  21. 21
      uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/Framebuffer.js
  22. 298
      uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/GLenum.js
  23. 142
      uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/GLmethod.js
  24. 23
      uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/GLtype.js
  25. 21
      uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/Program.js
  26. 21
      uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/Renderbuffer.js
  27. 1191
      uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/RenderingContext.js
  28. 22
      uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/Shader.js
  29. 11
      uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/ShaderPrecisionFormat.js
  30. 22
      uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/Texture.js
  31. 22
      uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/UniformLocation.js
  32. 3
      uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/context-webgl/classUtils.js
  33. 74
      uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/env/canvas.js
  34. 96
      uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/env/image.js
  35. 24
      uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/env/tool.js
  36. 39
      uni_modules/Sansnn-uQRCode/components/u-qrcode/gcanvas/index.js
  37. 684
      uni_modules/Sansnn-uQRCode/components/u-qrcode/u-qrcode.vue
  38. 201
      uni_modules/Sansnn-uQRCode/js_sdk/u-qrcode/license.md
  39. 2285
      uni_modules/Sansnn-uQRCode/js_sdk/u-qrcode/module.js
  40. 24
      uni_modules/Sansnn-uQRCode/js_sdk/u-qrcode/package.json
  41. 274
      uni_modules/Sansnn-uQRCode/js_sdk/u-qrcode/readme.md
  42. 2285
      uni_modules/Sansnn-uQRCode/js_sdk/u-qrcode/u-qrcode.js
  43. 83
      uni_modules/Sansnn-uQRCode/package.json
  44. 274
      uni_modules/Sansnn-uQRCode/readme.md

@ -25,6 +25,10 @@ export const list = (data) => {
return post('nakadai/applets/order/getOrderBasedOnBusinessManagerId', data)
}
export const all = (data) => {
return post('nakadai/applets/order/allTeamOrders', data)
}
export const del = (data) => {
return post('nakadai/nakadai/order/delete', data)
}

@ -6,13 +6,9 @@ export const savePartnerAccount = (data) => {
}
export const teamList = (data) => {
return get('nakadai/partner-team/teamList', data)
return post('nakadai/partnerAccount/partnerAccountList', data)
}
export const generateInvitationCode = (data) => {
return post('nakadai/partnerAccount/generateInvitationCode', data)
}
export const generationQrCode = (data) => {
return get('nakadai/partnerAccount/generationQrCode ', data)
export const generateInvitationCode = accountId => {
return post(`nakadai/partnerAccount/generateInvitationCode?accountId=${accountId}`)
}

@ -12,8 +12,8 @@ const request = options => {
})
}
const header = Object.assign({}, config.headers, {
// token: uni.getStorageSync('token')
token: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1c2VyIiwiaWF0IjoxNjU0NTY5OTA1LCJleHAiOjE2NTQ2MTMxMDUsImFjY291bnRJZCI6IjQ1MiJ9.IwVDQSpfYctr3ScaBiwXApNiSFjfwVbivt_uLCEPiW0'
token: uni.getStorageSync('token')
// token: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1c2VyIiwiaWF0IjoxNjU0NTY5OTA1LCJleHAiOjE2NTQ2MTMxMDUsImFjY291bnRJZCI6IjQ1MiJ9.IwVDQSpfYctr3ScaBiwXApNiSFjfwVbivt_uLCEPiW0'
})
return new Promise((resolve, reject)=>{
const { url } = options
@ -23,13 +23,18 @@ const request = options => {
method: options.method || 'GET', // 请求类型,默认为GET
data: options.data || {}, // 请求参数,默认空对象
success: ({ data }) => {
const { status, message } = data
// 状态判断,根据后台定义并提示
if (data.status === 200) {
if (status === 200) {
resolve(data)
} else if (data.status == 401) {
} else if (status == 401) {
// 登录过期
uni.removeStorageSync('token')
uni.removeStorageSync('userName')
uni.removeStorageSync('avatar')
uni.removeStorageSync('sessionKey')
uni.showToast({
title: data.message,
title: message,
icon: 'none'
})
setTimeout(() => {
@ -38,9 +43,11 @@ const request = options => {
})
}, 1500)
reject(data)
} else if (!status) {
resolve(data)
} else {
uni.showToast({
title: data.message,
title: message,
icon: 'none'
})
reject(data)

@ -5,7 +5,7 @@
*/
export default {
baseURL: 'http://192.168.31.151:9000/',
baseURL: 'http://192.168.31.137:9000/',
headers: {
'Content-Type': 'application/json;charset=UTF-8'
},

@ -22,6 +22,10 @@ export default {
handleNaN(val) {
return isNaN(val) ? 0 : val
},
// 小于10,返回0+传入值
preZero(val) {
return val < 10 ? '0' + val : val
},
//返回格式化时间,传参例如:"yyyy-MM-dd hh:mm:ss"
formatDate(date, fmt = 'yyyy-MM-dd hh:mm:ss') {
var date = date ? date : new Date()

@ -9,18 +9,26 @@
}
},
{
"path" : "pages/invite/invite",
"path" : "pages/index/index",
"style" :
{
"navigationBarTitleText": "加入团队",
"navigationBarTitleText": "",
"enablePullDownRefresh": false
}
},
{
"path" : "pages/index/index",
"path" : "pages/qrcode/qrcode",
"style" :
{
"navigationBarTitleText": "",
"navigationBarTitleText": "邀请加入",
"enablePullDownRefresh": false
}
},
{
"path" : "pages/invite/invite",
"style" :
{
"navigationBarTitleText": "加入团队",
"enablePullDownRefresh": false
}
},
@ -96,14 +104,6 @@
"enablePullDownRefresh": false
}
},
{
"path" : "pages/qrcode/qrcode",
"style" :
{
"navigationBarTitleText": "邀请加入",
"enablePullDownRefresh": false
}
},
{
"path" : "pages/send/send",
"style" :
@ -133,7 +133,7 @@
"style" :
{
"navigationBarTitleText": "团队",
"enablePullDownRefresh": false
"enablePullDownRefresh": true
}
},
{

@ -2,7 +2,7 @@
<view>
<uni-section title="邀请员工" type="line">
<uni-list>
<uni-list-item thumb-size="sm" showArrow title="二维码邀请" clickable>
<uni-list-item thumb-size="sm" showArrow title="二维码邀请" clickable :to="`../qrcode/qrcode`">
<template v-slot:header>
<view class="slot-box">
<image class="icon" src="@/static/image/qrcode.png" mode="widthFix"></image>

@ -133,13 +133,15 @@
methods: {
getList() {
const method = this.curTab ? all : list
method({
const data = {
businessManagerId: this.$util.getBmId(),
customerType: this.customerType,
keywords: this.keyword,
pageNum: this.page,
pageSize: this.pageSize
}).then(({ data }) => {
}
if (this.curTab) data.businessManagerIds = uni.getStorageSync('team').businessManagerIds
method(data).then(({ data }) => {
// list
this.list = this.reachBottom > 0 ? [...this.list, ...data.records] : data.records
this.page++ // page+1

@ -20,7 +20,6 @@
<view class="agree">
<uni-data-checkbox class="check" multiple v-model="agree" :localdata="agreeData"></uni-data-checkbox>
同意
<text @click="toAgreement(0)">用户服务协议</text>
<text @click="toAgreement(1)">用户隐私协议</text>
</view>
@ -36,7 +35,7 @@
return {
agree: [],
agreeData: [{
text: '',
text: '同意',
value: 1
}],
isLogin: true, //
@ -44,6 +43,7 @@
sessionKey: '',
openId: '',
unionid: '',
submiting: false
}
},
onShow() {
@ -63,6 +63,7 @@
//
login() {
if (this.agree.length) {
if (this.submiting) return false
const that = this
uni.getUserProfile({
lang: 'zh_CN',
@ -73,12 +74,14 @@
uni.login({
success: ({ code }) => {
if (code) {
this.submiting = true
login({ code }).then(({ data }) => {
const e = data.sessionKey
this.sessionKey = e.session_key
this.openId = e.openid
this.unionid = e.unionid
uni.setStorageSync('sessionKey', e.session_key)
this.submiting = false
//
if (data.state === 'login') {
this.toIndex()
@ -86,8 +89,11 @@
} else {
this.isLogin = true
}
}).catch(e => {})
}).catch(e => {
this.submiting = false
})
} else {
this.submiting = false
that.$util.errMsg('登录失败!')
}
}
@ -102,21 +108,30 @@
}
},
onGetPhoneNumber(e){
if (this.submiting) return false
const { encryptedData, iv } = e.detail
// 1.使js2.使
// const WXBizDataCrypt = require('@/libs/WXBizDataCrypt')
const accountInfo = uni.getAccountInfoSync() // appid
const pc = new WXBizDataCrypt(accountInfo.miniProgram.appId , this.sessionKey)
const data = pc.decryptData(encryptedData , iv)
this.submiting = true
//
userBinding({
openId: this.openId,
phone: data.phoneNumber,
unionid: this.unionid
}).then(({ token }) => {
this.submiting = false
uni.setStorageSync('token', token)
this.toIndex()
}).catch(e => {})
}).catch(e => {
this.submiting = false
uni.showToast({
title: e.message,
icon: 'none'
})
})
},
toAgreement(id) {
this.$util.to('../detail/detail?id=' + id)
@ -202,8 +217,14 @@
margin: 0;
}
.checkbox__inner {
width: 40rpx !important;
height: 40rpx !important;
border-radius: 50% !important;
}
.checkbox__inner-icon {
top: 8rpx !important;
left: 14rpx !important;
}
}
}
</style>

@ -63,7 +63,7 @@
<script>
import { queryCustomer } from '@/apis/modules/client.js'
import { list, del } from '@/apis/modules/order.js'
import { list, all, del } from '@/apis/modules/order.js'
import slFilter from '@/components/sl-filter/sl-filter.vue'
export default {
data() {
@ -171,14 +171,17 @@
},
methods: {
getList() {
list({
const method = this.curTab ? all : list
const data = {
businessManagerId: this.$util.getBmId(),
keywords: this.keyword,
pageNum: this.page,
pageSize: this.pageSize,
sort: this.sort,
orderStatus: this.orderStatus
}).then(({ data }) => {
}
if (this.curTab) data.businessManagerIds = uni.getStorageSync('team').businessManagerIds
method(data).then(({ data }) => {
// list
const list = data.records
list.map(e => {
@ -209,6 +212,7 @@
// tab
tabChange(tab) {
this.curTab = tab.id
this.initList()
},
//
toDetail(item) {

@ -2,38 +2,64 @@
<view class="page">
<view class="wrap">
<view class="info">
<image class="avatar" src="@/static/image/avatar.png" mode=""></image>
<image class="avatar" :src="avatar" mode=""></image>
<view class="text">
<view class="invite">
<text class="name">Jane</text> 邀请你加入
<text class="name">{{ userName }}</text> 邀请你加入
</view>
<view class="com">宁德时代股份有限公司</view>
<view class="com">{{ team.partnerClassificationName }}</view>
</view>
</view>
<image class="qrcode" src="https://pic.baike.soso.com/p/20130307/20130307133645-1010261466.jpg" mode=""></image>
<view class="qrcode">
<u-qrcode ref="qrcode" canvas-id="qrcode" :size="size" :value="link"></u-qrcode>
</view>
<view class="tips">扫一扫加入我们吧</view>
<view class="warn">邀请二维码失效日期2022年2月2日</view>
<view class="warn">邀请二维码失效日期{{ expireTime }}</view>
</view>
</view>
</template>
<script>
import { generateInvitationCode } from '@/apis/modules/parner.js'
export default {
data() {
return {
avatar: uni.getStorageSync('avatar') || '@/static/image/avatar.png',
userName: uni.getStorageSync('userName'),
expireTime: '',
qrcode: '',
link: '',
size: uni.upx2px(420),
team: uni.getStorageSync('team')
}
},
methods: {
onShow() {
this.getQrcode()
},
methods: {
//
getQrcode() {
const { team } = this
generateInvitationCode(uni.getStorageSync('team').accountId).then(({ expireTime }) => {
const date = new Date(Date.now() + expireTime * 1000) // *1000
this.expireTime = `${date.getFullYear()}-${this.$util.preZero(date.getMonth() + 1)}-${this.$util.preZero(date.getDate())} ${this.$util.preZero(date.getHours())}:${this.$util.preZero(date.getMinutes())}:${this.$util.preZero(date.getMinutes())}`
const team = this.team
// this.link = `http://39.108.250.202/nakadai/#/join?accountId=${team.accountId}&id=${team.partnerId}`
this.link = `http://192.168.31.126:8086/#/join?accountId=${team.accountId}&id=${team.teamId}&isTeam=0`
}).catch(e => {})
},
}
}
</script>
<style scoped lang="scss">
.page {
overflow: hidden;
}
.wrap {
padding: 20px 40px;
margin: 60px 40px 0;
padding: 40rpx 80rpx;
margin: 120rpx 80rpx 0;
text-align: center;
background-color: #fff;
.info {
@ -42,34 +68,33 @@
text-align: left;
}
.avatar {
width: 40px;
height: 40px;
margin-right: 10px;
width: 80rpx;
height: 80rpx;
margin-right: 20rpx;
border-radius: 50%;
}
.invite {
margin-bottom: 5px;
font-size: 15px;
margin-bottom: 10rpx;
font-size: 26rpx;
}
.name {
font-size: 13px;
margin-right: 5rpx;
font-size: 30rpx;
color: $uni-primary;
}
.com {
font-size: 13px;
font-size: 30rpx;
}
.qrcode {
width: 280px;
height: 280px;
margin-top: 20px;
margin-top: 80rpx;
}
.tips {
margin: 10px 0 10px;
margin: 80rpx 0 20rpx;
font-size: 12px;
color: #333;
}
.warn {
font-size: 12px;
font-size: 24rpx;
color: #f00;
}
}

@ -4,16 +4,26 @@
<uni-search-bar class="search" radius="5" placeholder="请输入成员名称" clearButton="auto" cancelButton="none" v-model="keyword" />
</uni-card>
<ul class="list">
<li v-for="item in list">
<image class="avatar" src="@/static/image/avatar.png" mode=""></image>
<view class="info">
<view class="name">Luna</view>
<view class="text">手机号码1352351253</view>
<view class="text">加入时间2020-01-02</view>
</view>
</li>
</ul>
<template v-if="list.length">
<ul class="list">
<li v-for="item in list">
<image class="avatar" src="@/static/image/avatar.png" mode=""></image>
<view class="info">
<view class="c-name">{{ item.userName }}</view>
<view class="line">
<text class="name">手机号码</text>
<text class="val">{{ item.phone }}</text>
</view>
<view class="line">
<text class="name">加入时间</text>
<text class="val">{{ item.lastLoginTime.split(' ')[0] }}</text>
</view>
</view>
</li>
</ul>
<uni-load-more :status="status" />
</template>
<empty v-else></empty>
<uni-icons class="plus" type="plus-filled" size="60" color="#007eff" @click="$util.to('../addStaff/addStaff')"></uni-icons>
</view>
@ -62,12 +72,16 @@
methods: {
getList() {
teamList({
id: uni.getStorageSync('team').teamId
}).then(({ data }) => {
pageNum: this.page,
pageSize: this.pageSize,
keyWord: this.keyword,
partnerClassificationId: uni.getStorageSync('team').teamId
}).then(({ pageList }) => {
const { records } = pageList
// list
this.list = this.reachBottom > 0 ? [...this.list, ...data.records] : data.records
this.list = this.reachBottom > 0 ? [...this.list, ...records] : records
this.page++ // page+1
const noMore = this.list.length === data.total //
const noMore = this.list.length === pageList.total //
this.status = noMore ? 'noMore' : 'more' // noMore
this.reachBottom = noMore ? -1 : 0 // -1
}).catch(e => {})
@ -83,35 +97,46 @@
<style scoped lang="scss">
.list {
margin-top: 10px;
margin-top: 20rpx;
background-color: #fff;
li {
display: flex;
align-items: center;
padding: 10px 20px;
padding: 20rpx 40rpx;
border-bottom: 1px solid #f7f7f7;
&:last-child {
border-bottom: 0;
}
}
.avatar {
width: 40px;
height: 40px;
margin-right: 15px;
width: 100rpx;
height: 100rpx;
margin-right: 30rpx;
border-radius: 50%;
}
.name {
font-size: 14px;
.c-name {
margin-bottom: 6rpx;
font-size: 30rpx;
color: #333;
}
.text {
font-size: 13px;
color: #858585;
.line {
display: flex;
padding: 2rpx 0;
}
.name {
margin-right: 10rpx;
white-space: nowrap;
font-size: 28rpx;
color: #999;
}
.val {
font-size: 28rpx;
color: #333;
}
}
.plus {
position: fixed;
bottom: 20px;
right: 20px;
bottom: 40rpx;
right: 40rpx;
}
</style>

@ -0,0 +1,44 @@
## 3.2.2(2022-05-12)
3.2.2
修复vue3引入js报错问题;
增加draw可选项,可在每一阶段绘制前后扩展自定义方法,详见文档draw(options);
其他优化。
## 3.2.1(2022-05-09)
3.2.1
已实现导入临时文件方法`toTempFilePath`;
已实现保存二维码到本地或相册方法`save`;
已实现生成完成回调事件`complete`;
文档补充。
## 3.2.0(2022-05-07)
3.2.0
适用所有支持canvas的前端应用和Node.js服务端;
微信小程序端切换为canvas2d;
支持绘制背景图片和前景图片,也就是说可以绘制背景和logo了;
支持对定位角进行样式设置;
支持对分割图案进行样式设置;
支持对对齐图案进行样式设置;
支持对时序图案进行样式设置;
支持对暗块进行样式设置;
支持对版本信息进行样式设置;
解决小块之间出现白线问题。
## 3.0.1(2022-01-05)
3.0.1 gcanvas引用目录调整。
## 3.0.0(2022-01-04)
3.0.0 uQRCode 3.0 全新版本来袭。
## 2.0.4(2021-11-19)
2.0.4 新增绘制模式;新增绘制延时、canvas导入文件延时属性。
## 2.0.3(2021-10-18)
2.0.3 修复在部分安卓设备生成异常;移除延迟绘制;新增批量生成示例。
## 2.0.23(2021-08-09)
## 2.0.22(2021-08-09)
## 2.0.21(2021-07-28)
## 2.0.2(2021-07-28)
2.0.2 新增延迟绘制。
## 2.0.1(2021-07-26)
2.0.1 调整为uni_modules目录规范。

@ -0,0 +1,241 @@
const isWeex = typeof WXEnvironment !== 'undefined';
const isWeexIOS = isWeex && /ios/i.test(WXEnvironment.platform);
const isWeexAndroid = isWeex && !isWeexIOS;
import GLmethod from '../context-webgl/GLmethod';
const GCanvasModule =
(typeof weex !== 'undefined' && weex.requireModule) ? (weex.requireModule('gcanvas')) :
(typeof __weex_require__ !== 'undefined') ? (__weex_require__('@weex-module/gcanvas')) : {};
let isDebugging = false;
let isComboDisabled = false;
const logCommand = (function () {
const methodQuery = [];
Object.keys(GLmethod).forEach(key => {
methodQuery[GLmethod[key]] = key;
})
const queryMethod = (id) => {
return methodQuery[parseInt(id)] || 'NotFoundMethod';
}
const logCommand = (id, cmds) => {
const mId = cmds.split(',')[0];
const mName = queryMethod(mId);
console.log(`=== callNative - componentId:${id}; method: ${mName}; cmds: ${cmds}`);
}
return logCommand;
})();
function joinArray(arr, sep) {
let res = '';
for (let i = 0; i < arr.length; i++) {
if (i !== 0) {
res += sep;
}
res += arr[i];
}
return res;
}
const commandsCache = {}
const GBridge = {
callEnable: (ref, configArray) => {
commandsCache[ref] = [];
return GCanvasModule.enable({
componentId: ref,
config: configArray
});
},
callEnableDebug: () => {
isDebugging = true;
},
callEnableDisableCombo: () => {
isComboDisabled = true;
},
callSetContextType: function (componentId, context_type) {
GCanvasModule.setContextType(context_type, componentId);
},
callReset: function(id){
GCanvasModule.resetComponent && canvasModule.resetComponent(componentId);
},
render: isWeexIOS ? function (componentId) {
return GCanvasModule.extendCallNative({
contextId: componentId,
type: 0x60000001
});
} : function (componentId) {
return callGCanvasLinkNative(componentId, 0x60000001, 'render');
},
render2d: isWeexIOS ? function (componentId, commands, callback) {
if (isDebugging) {
console.log('>>> >>> render2d ===');
console.log('>>> commands: ' + commands);
}
GCanvasModule.render([commands, callback?true:false], componentId, callback);
} : function (componentId, commands,callback) {
if (isDebugging) {
console.log('>>> >>> render2d ===');
console.log('>>> commands: ' + commands);
}
callGCanvasLinkNative(componentId, 0x20000001, commands);
if(callback){
callback();
}
},
callExtendCallNative: isWeexIOS ? function (componentId, cmdArgs) {
throw 'should not be here anymore ' + cmdArgs;
} : function (componentId, cmdArgs) {
throw 'should not be here anymore ' + cmdArgs;
},
flushNative: isWeexIOS ? function (componentId) {
const cmdArgs = joinArray(commandsCache[componentId], ';');
commandsCache[componentId] = [];
if (isDebugging) {
console.log('>>> >>> flush native ===');
console.log('>>> commands: ' + cmdArgs);
}
const result = GCanvasModule.extendCallNative({
"contextId": componentId,
"type": 0x60000000,
"args": cmdArgs
});
const res = result && result.result;
if (isDebugging) {
console.log('>>> result: ' + res);
}
return res;
} : function (componentId) {
const cmdArgs = joinArray(commandsCache[componentId], ';');
commandsCache[componentId] = [];
if (isDebugging) {
console.log('>>> >>> flush native ===');
console.log('>>> commands: ' + cmdArgs);
}
const result = callGCanvasLinkNative(componentId, 0x60000000, cmdArgs);
if (isDebugging) {
console.log('>>> result: ' + result);
}
return result;
},
callNative: function (componentId, cmdArgs, cache) {
if (isDebugging) {
logCommand(componentId, cmdArgs);
}
commandsCache[componentId].push(cmdArgs);
if (!cache || isComboDisabled) {
return GBridge.flushNative(componentId);
} else {
return undefined;
}
},
texImage2D(componentId, ...args) {
if (isWeexIOS) {
if (args.length === 6) {
const [target, level, internalformat, format, type, image] = args;
GBridge.callNative(
componentId,
GLmethod.texImage2D + ',' + 6 + ',' + target + ',' + level + ',' + internalformat + ',' + format + ',' + type + ',' + image.src
)
} else if (args.length === 9) {
const [target, level, internalformat, width, height, border, format, type, image] = args;
GBridge.callNative(
componentId,
GLmethod.texImage2D + ',' + 9 + ',' + target + ',' + level + ',' + internalformat + ',' + width + ',' + height + ',' + border + ',' +
+ format + ',' + type + ',' + (image ? image.src : 0)
)
}
} else if (isWeexAndroid) {
if (args.length === 6) {
const [target, level, internalformat, format, type, image] = args;
GCanvasModule.texImage2D(componentId, target, level, internalformat, format, type, image.src);
} else if (args.length === 9) {
const [target, level, internalformat, width, height, border, format, type, image] = args;
GCanvasModule.texImage2D(componentId, target, level, internalformat, width, height, border, format, type, (image ? image.src : 0));
}
}
},
texSubImage2D(componentId, target, level, xoffset, yoffset, format, type, image) {
if (isWeexIOS) {
if (arguments.length === 8) {
GBridge.callNative(
componentId,
GLmethod.texSubImage2D + ',' + 6 + ',' + target + ',' + level + ',' + xoffset + ',' + yoffset, + ',' + format + ',' + type + ',' + image.src
)
}
} else if (isWeexAndroid) {
GCanvasModule.texSubImage2D(componentId, target, level, xoffset, yoffset, format, type, image.src);
}
},
bindImageTexture(componentId, src, imageId) {
GCanvasModule.bindImageTexture([src, imageId], componentId);
},
perloadImage([url, id], callback) {
GCanvasModule.preLoadImage([url, id], function (image) {
image.url = url;
image.id = id;
callback(image);
});
},
measureText(text, fontStyle, componentId) {
return GCanvasModule.measureText([text, fontStyle], componentId);
},
getImageData (componentId, x, y, w, h, callback) {
GCanvasModule.getImageData([x, y,w,h],componentId,callback);
},
putImageData (componentId, data, x, y, w, h, callback) {
GCanvasModule.putImageData([x, y,w,h,data],componentId,callback);
},
toTempFilePath(componentId, x, y, width, height, destWidth, destHeight, fileType, quality, callback){
GCanvasModule.toTempFilePath([x, y, width,height, destWidth, destHeight, fileType, quality], componentId, callback);
}
}
export default GBridge;

@ -0,0 +1,18 @@
class FillStyleLinearGradient {
constructor(x0, y0, x1, y1) {
this._start_pos = { _x: x0, _y: y0 };
this._end_pos = { _x: x1, _y: y1 };
this._stop_count = 0;
this._stops = [0, 0, 0, 0, 0];
}
addColorStop = function (pos, color) {
if (this._stop_count < 5 && 0.0 <= pos && pos <= 1.0) {
this._stops[this._stop_count] = { _pos: pos, _color: color };
this._stop_count++;
}
}
}
export default FillStyleLinearGradient;

@ -0,0 +1,8 @@
class FillStylePattern {
constructor(img, pattern) {
this._style = pattern;
this._img = img;
}
}
export default FillStylePattern;

@ -0,0 +1,17 @@
class FillStyleRadialGradient {
constructor(x0, y0, r0, x1, y1, r1) {
this._start_pos = { _x: x0, _y: y0, _r: r0 };
this._end_pos = { _x: x1, _y: y1, _r: r1 };
this._stop_count = 0;
this._stops = [0, 0, 0, 0, 0];
}
addColorStop(pos, color) {
if (this._stop_count < 5 && 0.0 <= pos && pos <= 1.0) {
this._stops[this._stop_count] = { _pos: pos, _color: color };
this._stop_count++;
}
}
}
export default FillStyleRadialGradient;

@ -0,0 +1,666 @@
import FillStylePattern from './FillStylePattern';
import FillStyleLinearGradient from './FillStyleLinearGradient';
import FillStyleRadialGradient from './FillStyleRadialGradient';
import GImage from '../env/image.js';
import {
ArrayBufferToBase64,
Base64ToUint8ClampedArray
} from '../env/tool.js';
export default class CanvasRenderingContext2D {
_drawCommands = '';
_globalAlpha = 1.0;
_fillStyle = 'rgb(0,0,0)';
_strokeStyle = 'rgb(0,0,0)';
_lineWidth = 1;
_lineCap = 'butt';
_lineJoin = 'miter';
_miterLimit = 10;
_globalCompositeOperation = 'source-over';
_textAlign = 'start';
_textBaseline = 'alphabetic';
_font = '10px sans-serif';
_savedGlobalAlpha = [];
timer = null;
componentId = null;
_notCommitDrawImageCache = [];
_needRedrawImageCache = [];
_redrawCommands = '';
_autoSaveContext = true;
// _imageMap = new GHashMap();
// _textureMap = new GHashMap();
constructor() {
this.className = 'CanvasRenderingContext2D';
//this.save()
}
setFillStyle(value) {
this.fillStyle = value;
}
set fillStyle(value) {
this._fillStyle = value;
if (typeof(value) == 'string') {
this._drawCommands = this._drawCommands.concat("F" + value + ";");
} else if (value instanceof FillStylePattern) {
const image = value._img;
if (!image.complete) {
image.onload = () => {
var index = this._needRedrawImageCache.indexOf(image);
if (index > -1) {
this._needRedrawImageCache.splice(index, 1);
CanvasRenderingContext2D.GBridge.bindImageTexture(this.componentId, image.src, image._id);
this._redrawflush(true);
}
}
this._notCommitDrawImageCache.push(image);
} else {
CanvasRenderingContext2D.GBridge.bindImageTexture(this.componentId, image.src, image._id);
}
//CanvasRenderingContext2D.GBridge.bindImageTexture(this.componentId, image.src, image._id);
this._drawCommands = this._drawCommands.concat("G" + image._id + "," + value._style + ";");
} else if (value instanceof FillStyleLinearGradient) {
var command = "D" + value._start_pos._x.toFixed(2) + "," + value._start_pos._y.toFixed(2) + "," +
value._end_pos._x.toFixed(2) + "," + value._end_pos._y.toFixed(2) + "," +
value._stop_count;
for (var i = 0; i < value._stop_count; ++i) {
command += ("," + value._stops[i]._pos + "," + value._stops[i]._color);
}
this._drawCommands = this._drawCommands.concat(command + ";");
} else if (value instanceof FillStyleRadialGradient) {
var command = "H" + value._start_pos._x.toFixed(2) + "," + value._start_pos._y.toFixed(2) + "," + value._start_pos._r
.toFixed(2) + "," +
value._end_pos._x.toFixed(2) + "," + value._end_pos._y.toFixed(2) + "," + value._end_pos._r.toFixed(2) + "," +
value._stop_count;
for (var i = 0; i < value._stop_count; ++i) {
command += ("," + value._stops[i]._pos + "," + value._stops[i]._color);
}
this._drawCommands = this._drawCommands.concat(command + ";");
}
}
get fillStyle() {
return this._fillStyle;
}
get globalAlpha() {
return this._globalAlpha;
}
setGlobalAlpha(value) {
this.globalAlpha = value;
}
set globalAlpha(value) {
this._globalAlpha = value;
this._drawCommands = this._drawCommands.concat("a" + value.toFixed(2) + ";");
}
get strokeStyle() {
return this._strokeStyle;
}
setStrokeStyle(value) {
this.strokeStyle = value;
}
set strokeStyle(value) {
this._strokeStyle = value;
if (typeof(value) == 'string') {
this._drawCommands = this._drawCommands.concat("S" + value + ";");
} else if (value instanceof FillStylePattern) {
CanvasRenderingContext2D.GBridge.bindImageTexture(this.componentId, image.src, image._id);
this._drawCommands = this._drawCommands.concat("G" + image._id + "," + value._style + ";");
} else if (value instanceof FillStyleLinearGradient) {
var command = "D" + value._start_pos._x.toFixed(2) + "," + value._start_pos._y.toFixed(2) + "," +
value._end_pos._x.toFixed(2) + "," + value._end_pos._y.toFixed(2) + "," +
value._stop_count;
for (var i = 0; i < value._stop_count; ++i) {
command += ("," + value._stops[i]._pos + "," + value._stops[i]._color);
}
this._drawCommands = this._drawCommands.concat(command + ";");
} else if (value instanceof FillStyleRadialGradient) {
var command = "H" + value._start_pos._x.toFixed(2) + "," + value._start_pos._y.toFixed(2) + "," + value._start_pos._r
.toFixed(2) + "," +
value._end_pos._x.toFixed(2) + "," + value._end_pos._y + ",".toFixed(2) + value._end_pos._r.toFixed(2) + "," +
value._stop_count;
for (var i = 0; i < value._stop_count; ++i) {
command += ("," + value._stops[i]._pos + "," + value._stops[i]._color);
}
this._drawCommands = this._drawCommands.concat(command + ";");
}
}
get lineWidth() {
return this._lineWidth;
}
setLineWidth(value) {
this.lineWidth = value;
}
set lineWidth(value) {
this._lineWidth = value;
this._drawCommands = this._drawCommands.concat("W" + value + ";");
}
get lineCap() {
return this._lineCap;
}
setLineCap(value) {
this.lineCap = value;
}
set lineCap(value) {
this._lineCap = value;
this._drawCommands = this._drawCommands.concat("C" + value + ";");
}
get lineJoin() {
return this._lineJoin;
}
setLineJoin(value) {
this.lineJoin = value
}
set lineJoin(value) {
this._lineJoin = value;
this._drawCommands = this._drawCommands.concat("J" + value + ";");
}
get miterLimit() {
return this._miterLimit;
}
setMiterLimit(value) {
this.miterLimit = value
}
set miterLimit(value) {
this._miterLimit = value;
this._drawCommands = this._drawCommands.concat("M" + value + ";");
}
get globalCompositeOperation() {
return this._globalCompositeOperation;
}
set globalCompositeOperation(value) {
this._globalCompositeOperation = value;
let mode = 0;
switch (value) {
case "source-over":
mode = 0;
break;
case "source-atop":
mode = 5;
break;
case "source-in":
mode = 0;
break;
case "source-out":
mode = 2;
break;
case "destination-over":
mode = 4;
break;
case "destination-atop":
mode = 4;
break;
case "destination-in":
mode = 4;
break;
case "destination-out":
mode = 3;
break;
case "lighter":
mode = 1;
break;
case "copy":
mode = 2;
break;
case "xor":
mode = 6;
break;
default:
mode = 0;
}
this._drawCommands = this._drawCommands.concat("B" + mode + ";");
}
get textAlign() {
return this._textAlign;
}
setTextAlign(value) {
this.textAlign = value
}
set textAlign(value) {
this._textAlign = value;
let Align = 0;
switch (value) {
case "start":
Align = 0;
break;
case "end":
Align = 1;
break;
case "left":
Align = 2;
break;
case "center":
Align = 3;
break;
case "right":
Align = 4;
break;
default:
Align = 0;
}
this._drawCommands = this._drawCommands.concat("A" + Align + ";");
}
get textBaseline() {
return this._textBaseline;
}
setTextBaseline(value) {
this.textBaseline = value
}
set textBaseline(value) {
this._textBaseline = value;
let baseline = 0;
switch (value) {
case "alphabetic":
baseline = 0;
break;
case "middle":
baseline = 1;
break;
case "top":
baseline = 2;
break;
case "hanging":
baseline = 3;
break;
case "bottom":
baseline = 4;
break;
case "ideographic":
baseline = 5;
break;
default:
baseline = 0;
break;
}
this._drawCommands = this._drawCommands.concat("E" + baseline + ";");
}
get font() {
return this._font;
}
setFontSize(size) {
var str = this._font;
var strs = str.trim().split(/\s+/);
for (var i = 0; i < strs.length; i++) {
var values = ["normal", "italic", "oblique", "normal", "small-caps", "normal", "bold",
"bolder", "lighter", "100", "200", "300", "400", "500", "600", "700", "800", "900",
"normal", "ultra-condensed", "extra-condensed", "condensed", "semi-condensed",
"semi-expanded", "expanded", "extra-expanded", "ultra-expanded"
];
if (-1 == values.indexOf(strs[i].trim())) {
if (typeof size === 'string') {
strs[i] = size;
} else if (typeof size === 'number') {
strs[i] = String(size) + 'px';
}
break;
}
}
this.font = strs.join(" ");
}
set font(value) {
this._font = value;
this._drawCommands = this._drawCommands.concat("j" + value + ";");
}
setTransform(a, b, c, d, tx, ty) {
this._drawCommands = this._drawCommands.concat("t" +
(a === 1 ? "1" : a.toFixed(2)) + "," +
(b === 0 ? "0" : b.toFixed(2)) + "," +
(c === 0 ? "0" : c.toFixed(2)) + "," +
(d === 1 ? "1" : d.toFixed(2)) + "," + tx.toFixed(2) + "," + ty.toFixed(2) + ";");
}
transform(a, b, c, d, tx, ty) {
this._drawCommands = this._drawCommands.concat("f" +
(a === 1 ? "1" : a.toFixed(2)) + "," +
(b === 0 ? "0" : b.toFixed(2)) + "," +
(c === 0 ? "0" : c.toFixed(2)) + "," +
(d === 1 ? "1" : d.toFixed(2)) + "," + tx + "," + ty + ";");
}
resetTransform() {
this._drawCommands = this._drawCommands.concat("m;");
}
scale(a, d) {
this._drawCommands = this._drawCommands.concat("k" + a.toFixed(2) + "," +
d.toFixed(2) + ";");
}
rotate(angle) {
this._drawCommands = this._drawCommands
.concat("r" + angle.toFixed(6) + ";");
}
translate(tx, ty) {
this._drawCommands = this._drawCommands.concat("l" + tx.toFixed(2) + "," + ty.toFixed(2) + ";");
}
save() {
this._savedGlobalAlpha.push(this._globalAlpha);
this._drawCommands = this._drawCommands.concat("v;");
}
restore() {
this._drawCommands = this._drawCommands.concat("e;");
this._globalAlpha = this._savedGlobalAlpha.pop();
}
createPattern(img, pattern) {
if (typeof img === 'string') {
var imgObj = new GImage();
imgObj.src = img;
img = imgObj;
}
return new FillStylePattern(img, pattern);
}
createLinearGradient(x0, y0, x1, y1) {
return new FillStyleLinearGradient(x0, y0, x1, y1);
}
createRadialGradient = function(x0, y0, r0, x1, y1, r1) {
return new FillStyleRadialGradient(x0, y0, r0, x1, y1, r1);
};
createCircularGradient = function(x0, y0, r0) {
return new FillStyleRadialGradient(x0, y0, 0, x0, y0, r0);
};
strokeRect(x, y, w, h) {
this._drawCommands = this._drawCommands.concat("s" + x + "," + y + "," + w + "," + h + ";");
}
clearRect(x, y, w, h) {
this._drawCommands = this._drawCommands.concat("c" + x + "," + y + "," + w +
"," + h + ";");
}
clip() {
this._drawCommands = this._drawCommands.concat("p;");
}
resetClip() {
this._drawCommands = this._drawCommands.concat("q;");
}
closePath() {
this._drawCommands = this._drawCommands.concat("o;");
}
moveTo(x, y) {
this._drawCommands = this._drawCommands.concat("g" + x.toFixed(2) + "," + y.toFixed(2) + ";");
}
lineTo(x, y) {
this._drawCommands = this._drawCommands.concat("i" + x.toFixed(2) + "," + y.toFixed(2) + ";");
}
quadraticCurveTo = function(cpx, cpy, x, y) {
this._drawCommands = this._drawCommands.concat("u" + cpx + "," + cpy + "," + x + "," + y + ";");
}
bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y, ) {
this._drawCommands = this._drawCommands.concat(
"z" + cp1x.toFixed(2) + "," + cp1y.toFixed(2) + "," + cp2x.toFixed(2) + "," + cp2y.toFixed(2) + "," +
x.toFixed(2) + "," + y.toFixed(2) + ";");
}
arcTo(x1, y1, x2, y2, radius) {
this._drawCommands = this._drawCommands.concat("h" + x1 + "," + y1 + "," + x2 + "," + y2 + "," + radius + ";");
}
beginPath() {
this._drawCommands = this._drawCommands.concat("b;");
}
fillRect(x, y, w, h) {
this._drawCommands = this._drawCommands.concat("n" + x + "," + y + "," + w +
"," + h + ";");
}
rect(x, y, w, h) {
this._drawCommands = this._drawCommands.concat("w" + x + "," + y + "," + w + "," + h + ";");
}
fill() {
this._drawCommands = this._drawCommands.concat("L;");
}
stroke(path) {
this._drawCommands = this._drawCommands.concat("x;");
}
arc(x, y, radius, startAngle, endAngle, anticlockwise) {
let ianticlockwise = 0;
if (anticlockwise) {
ianticlockwise = 1;
}
this._drawCommands = this._drawCommands.concat(
"y" + x.toFixed(2) + "," + y.toFixed(2) + "," +
radius.toFixed(2) + "," + startAngle + "," + endAngle + "," + ianticlockwise +
";"
);
}
fillText(text, x, y) {
let tmptext = text.replace(/!/g, "!!");
tmptext = tmptext.replace(/,/g, "!,");
tmptext = tmptext.replace(/;/g, "!;");
this._drawCommands = this._drawCommands.concat("T" + tmptext + "," + x + "," + y + ",0.0;");
}
strokeText = function(text, x, y) {
let tmptext = text.replace(/!/g, "!!");
tmptext = tmptext.replace(/,/g, "!,");
tmptext = tmptext.replace(/;/g, "!;");
this._drawCommands = this._drawCommands.concat("U" + tmptext + "," + x + "," + y + ",0.0;");
}
measureText(text) {
return CanvasRenderingContext2D.GBridge.measureText(text, this.font, this.componentId);
}
isPointInPath = function(x, y) {
throw new Error('GCanvas not supported yet');
}
drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh) {
if (typeof image === 'string') {
var imgObj = new GImage();
imgObj.src = image;
image = imgObj;
}
if (image instanceof GImage) {
if (!image.complete) {
imgObj.onload = () => {
var index = this._needRedrawImageCache.indexOf(image);
if (index > -1) {
this._needRedrawImageCache.splice(index, 1);
CanvasRenderingContext2D.GBridge.bindImageTexture(this.componentId, image.src, image._id);
this._redrawflush(true);
}
}
this._notCommitDrawImageCache.push(image);
} else {
CanvasRenderingContext2D.GBridge.bindImageTexture(this.componentId, image.src, image._id);
}
var srcArgs = [image, sx, sy, sw, sh, dx, dy, dw, dh];
var args = [];
for (var arg in srcArgs) {
if (typeof(srcArgs[arg]) != 'undefined') {
args.push(srcArgs[arg]);
}
}
this.__drawImage.apply(this, args);
//this.__drawImage(image,sx, sy, sw, sh, dx, dy, dw, dh);
}
}
__drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh) {
const numArgs = arguments.length;
function drawImageCommands() {
if (numArgs === 3) {
const x = parseFloat(sx) || 0.0;
const y = parseFloat(sy) || 0.0;
return ("d" + image._id + ",0,0," +
image.width + "," + image.height + "," +
x + "," + y + "," + image.width + "," + image.height + ";");
} else if (numArgs === 5) {
const x = parseFloat(sx) || 0.0;
const y = parseFloat(sy) || 0.0;
const width = parseInt(sw) || image.width;
const height = parseInt(sh) || image.height;
return ("d" + image._id + ",0,0," +
image.width + "," + image.height + "," +
x + "," + y + "," + width + "," + height + ";");
} else if (numArgs === 9) {
sx = parseFloat(sx) || 0.0;
sy = parseFloat(sy) || 0.0;
sw = parseInt(sw) || image.width;
sh = parseInt(sh) || image.height;
dx = parseFloat(dx) || 0.0;
dy = parseFloat(dy) || 0.0;
dw = parseInt(dw) || image.width;
dh = parseInt(dh) || image.height;
return ("d" + image._id + "," +
sx + "," + sy + "," + sw + "," + sh + "," +
dx + "," + dy + "," + dw + "," + dh + ";");
}
}
this._drawCommands += drawImageCommands();
}
_flush(reserve, callback) {
const commands = this._drawCommands;
this._drawCommands = '';
CanvasRenderingContext2D.GBridge.render2d(this.componentId, commands, callback);
this._needRender = false;
}
_redrawflush(reserve, callback) {
const commands = this._redrawCommands;
CanvasRenderingContext2D.GBridge.render2d(this.componentId, commands, callback);
if (this._needRedrawImageCache.length == 0) {
this._redrawCommands = '';
}
}
draw(reserve, callback) {
if (!reserve) {
this._globalAlpha = this._savedGlobalAlpha.pop();
this._savedGlobalAlpha.push(this._globalAlpha);
this._redrawCommands = this._drawCommands;
this._needRedrawImageCache = this._notCommitDrawImageCache;
if (this._autoSaveContext) {
this._drawCommands = ("v;" + this._drawCommands);
this._autoSaveContext = false;
} else {
this._drawCommands = ("e;X;v;" + this._drawCommands);
}
} else {
this._needRedrawImageCache = this._needRedrawImageCache.concat(this._notCommitDrawImageCache);
this._redrawCommands += this._drawCommands;
if (this._autoSaveContext) {
this._drawCommands = ("v;" + this._drawCommands);
this._autoSaveContext = false;
}
}
this._notCommitDrawImageCache = [];
if (this._flush) {
this._flush(reserve, callback);
}
}
getImageData(x, y, w, h, callback) {
CanvasRenderingContext2D.GBridge.getImageData(this.componentId, x, y, w, h, function(res) {
res.data = Base64ToUint8ClampedArray(res.data);
if (typeof(callback) == 'function') {
callback(res);
}
});
}
putImageData(data, x, y, w, h, callback) {
if (data instanceof Uint8ClampedArray) {
data = ArrayBufferToBase64(data);
CanvasRenderingContext2D.GBridge.putImageData(this.componentId, data, x, y, w, h, function(res) {
if (typeof(callback) == 'function') {
callback(res);
}
});
}
}
toTempFilePath(x, y, width, height, destWidth, destHeight, fileType, quality, callback) {
CanvasRenderingContext2D.GBridge.toTempFilePath(this.componentId, x, y, width, height, destWidth, destHeight,
fileType, quality,
function(res) {
if (typeof(callback) == 'function') {
callback(res);
}
});
}
}

@ -0,0 +1,11 @@
export default class WebGLActiveInfo {
className = 'WebGLActiveInfo';
constructor({
type, name, size
}) {
this.type = type;
this.name = name;
this.size = size;
}
}

@ -0,0 +1,21 @@
import {getTransferedObjectUUID} from './classUtils';
const name = 'WebGLBuffer';
function uuid(id) {
return getTransferedObjectUUID(name, id);
}
export default class WebGLBuffer {
className = name;
constructor(id) {
this.id = id;
}
static uuid = uuid;
uuid() {
return uuid(this.id);
}
}

@ -0,0 +1,21 @@
import {getTransferedObjectUUID} from './classUtils';
const name = 'WebGLFrameBuffer';
function uuid(id) {
return getTransferedObjectUUID(name, id);
}
export default class WebGLFramebuffer {
className = name;
constructor(id) {
this.id = id;
}
static uuid = uuid;
uuid() {
return uuid(this.id);
}
}

@ -0,0 +1,298 @@
export default {
"DEPTH_BUFFER_BIT": 256,
"STENCIL_BUFFER_BIT": 1024,
"COLOR_BUFFER_BIT": 16384,
"POINTS": 0,
"LINES": 1,
"LINE_LOOP": 2,
"LINE_STRIP": 3,
"TRIANGLES": 4,
"TRIANGLE_STRIP": 5,
"TRIANGLE_FAN": 6,
"ZERO": 0,
"ONE": 1,
"SRC_COLOR": 768,
"ONE_MINUS_SRC_COLOR": 769,
"SRC_ALPHA": 770,
"ONE_MINUS_SRC_ALPHA": 771,
"DST_ALPHA": 772,
"ONE_MINUS_DST_ALPHA": 773,
"DST_COLOR": 774,
"ONE_MINUS_DST_COLOR": 775,
"SRC_ALPHA_SATURATE": 776,
"FUNC_ADD": 32774,
"BLEND_EQUATION": 32777,
"BLEND_EQUATION_RGB": 32777,
"BLEND_EQUATION_ALPHA": 34877,
"FUNC_SUBTRACT": 32778,
"FUNC_REVERSE_SUBTRACT": 32779,
"BLEND_DST_RGB": 32968,
"BLEND_SRC_RGB": 32969,
"BLEND_DST_ALPHA": 32970,
"BLEND_SRC_ALPHA": 32971,
"CONSTANT_COLOR": 32769,
"ONE_MINUS_CONSTANT_COLOR": 32770,
"CONSTANT_ALPHA": 32771,
"ONE_MINUS_CONSTANT_ALPHA": 32772,
"BLEND_COLOR": 32773,
"ARRAY_BUFFER": 34962,
"ELEMENT_ARRAY_BUFFER": 34963,
"ARRAY_BUFFER_BINDING": 34964,
"ELEMENT_ARRAY_BUFFER_BINDING": 34965,
"STREAM_DRAW": 35040,
"STATIC_DRAW": 35044,
"DYNAMIC_DRAW": 35048,
"BUFFER_SIZE": 34660,
"BUFFER_USAGE": 34661,
"CURRENT_VERTEX_ATTRIB": 34342,
"FRONT": 1028,
"BACK": 1029,
"FRONT_AND_BACK": 1032,
"TEXTURE_2D": 3553,
"CULL_FACE": 2884,
"BLEND": 3042,
"DITHER": 3024,
"STENCIL_TEST": 2960,
"DEPTH_TEST": 2929,
"SCISSOR_TEST": 3089,
"POLYGON_OFFSET_FILL": 32823,
"SAMPLE_ALPHA_TO_COVERAGE": 32926,
"SAMPLE_COVERAGE": 32928,
"NO_ERROR": 0,
"INVALID_ENUM": 1280,
"INVALID_VALUE": 1281,
"INVALID_OPERATION": 1282,
"OUT_OF_MEMORY": 1285,
"CW": 2304,
"CCW": 2305,
"LINE_WIDTH": 2849,
"ALIASED_POINT_SIZE_RANGE": 33901,
"ALIASED_LINE_WIDTH_RANGE": 33902,
"CULL_FACE_MODE": 2885,
"FRONT_FACE": 2886,
"DEPTH_RANGE": 2928,
"DEPTH_WRITEMASK": 2930,
"DEPTH_CLEAR_VALUE": 2931,
"DEPTH_FUNC": 2932,
"STENCIL_CLEAR_VALUE": 2961,
"STENCIL_FUNC": 2962,
"STENCIL_FAIL": 2964,
"STENCIL_PASS_DEPTH_FAIL": 2965,
"STENCIL_PASS_DEPTH_PASS": 2966,
"STENCIL_REF": 2967,
"STENCIL_VALUE_MASK": 2963,
"STENCIL_WRITEMASK": 2968,
"STENCIL_BACK_FUNC": 34816,
"STENCIL_BACK_FAIL": 34817,
"STENCIL_BACK_PASS_DEPTH_FAIL": 34818,
"STENCIL_BACK_PASS_DEPTH_PASS": 34819,
"STENCIL_BACK_REF": 36003,
"STENCIL_BACK_VALUE_MASK": 36004,
"STENCIL_BACK_WRITEMASK": 36005,
"VIEWPORT": 2978,
"SCISSOR_BOX": 3088,
"COLOR_CLEAR_VALUE": 3106,
"COLOR_WRITEMASK": 3107,
"UNPACK_ALIGNMENT": 3317,
"PACK_ALIGNMENT": 3333,
"MAX_TEXTURE_SIZE": 3379,
"MAX_VIEWPORT_DIMS": 3386,
"SUBPIXEL_BITS": 3408,
"RED_BITS": 3410,
"GREEN_BITS": 3411,
"BLUE_BITS": 3412,
"ALPHA_BITS": 3413,
"DEPTH_BITS": 3414,
"STENCIL_BITS": 3415,
"POLYGON_OFFSET_UNITS": 10752,
"POLYGON_OFFSET_FACTOR": 32824,
"TEXTURE_BINDING_2D": 32873,
"SAMPLE_BUFFERS": 32936,
"SAMPLES": 32937,
"SAMPLE_COVERAGE_VALUE": 32938,
"SAMPLE_COVERAGE_INVERT": 32939,
"COMPRESSED_TEXTURE_FORMATS": 34467,
"DONT_CARE": 4352,
"FASTEST": 4353,
"NICEST": 4354,
"GENERATE_MIPMAP_HINT": 33170,
"BYTE": 5120,
"UNSIGNED_BYTE": 5121,
"SHORT": 5122,
"UNSIGNED_SHORT": 5123,
"INT": 5124,
"UNSIGNED_INT": 5125,
"FLOAT": 5126,
"DEPTH_COMPONENT": 6402,
"ALPHA": 6406,
"RGB": 6407,
"RGBA": 6408,
"LUMINANCE": 6409,
"LUMINANCE_ALPHA": 6410,
"UNSIGNED_SHORT_4_4_4_4": 32819,
"UNSIGNED_SHORT_5_5_5_1": 32820,
"UNSIGNED_SHORT_5_6_5": 33635,
"FRAGMENT_SHADER": 35632,
"VERTEX_SHADER": 35633,
"MAX_VERTEX_ATTRIBS": 34921,
"MAX_VERTEX_UNIFORM_VECTORS": 36347,
"MAX_VARYING_VECTORS": 36348,
"MAX_COMBINED_TEXTURE_IMAGE_UNITS": 35661,
"MAX_VERTEX_TEXTURE_IMAGE_UNITS": 35660,
"MAX_TEXTURE_IMAGE_UNITS": 34930,
"MAX_FRAGMENT_UNIFORM_VECTORS": 36349,
"SHADER_TYPE": 35663,
"DELETE_STATUS": 35712,
"LINK_STATUS": 35714,
"VALIDATE_STATUS": 35715,
"ATTACHED_SHADERS": 35717,
"ACTIVE_UNIFORMS": 35718,
"ACTIVE_ATTRIBUTES": 35721,
"SHADING_LANGUAGE_VERSION": 35724,
"CURRENT_PROGRAM": 35725,
"NEVER": 512,
"LESS": 513,
"EQUAL": 514,
"LEQUAL": 515,
"GREATER": 516,
"NOTEQUAL": 517,
"GEQUAL": 518,
"ALWAYS": 519,
"KEEP": 7680,
"REPLACE": 7681,
"INCR": 7682,
"DECR": 7683,
"INVERT": 5386,
"INCR_WRAP": 34055,
"DECR_WRAP": 34056,
"VENDOR": 7936,
"RENDERER": 7937,
"VERSION": 7938,
"NEAREST": 9728,
"LINEAR": 9729,
"NEAREST_MIPMAP_NEAREST": 9984,
"LINEAR_MIPMAP_NEAREST": 9985,
"NEAREST_MIPMAP_LINEAR": 9986,
"LINEAR_MIPMAP_LINEAR": 9987,
"TEXTURE_MAG_FILTER": 10240,
"TEXTURE_MIN_FILTER": 10241,
"TEXTURE_WRAP_S": 10242,
"TEXTURE_WRAP_T": 10243,
"TEXTURE": 5890,
"TEXTURE_CUBE_MAP": 34067,
"TEXTURE_BINDING_CUBE_MAP": 34068,
"TEXTURE_CUBE_MAP_POSITIVE_X": 34069,
"TEXTURE_CUBE_MAP_NEGATIVE_X": 34070,
"TEXTURE_CUBE_MAP_POSITIVE_Y": 34071,
"TEXTURE_CUBE_MAP_NEGATIVE_Y": 34072,
"TEXTURE_CUBE_MAP_POSITIVE_Z": 34073,
"TEXTURE_CUBE_MAP_NEGATIVE_Z": 34074,
"MAX_CUBE_MAP_TEXTURE_SIZE": 34076,
"TEXTURE0": 33984,
"TEXTURE1": 33985,
"TEXTURE2": 33986,
"TEXTURE3": 33987,
"TEXTURE4": 33988,
"TEXTURE5": 33989,
"TEXTURE6": 33990,
"TEXTURE7": 33991,
"TEXTURE8": 33992,
"TEXTURE9": 33993,
"TEXTURE10": 33994,
"TEXTURE11": 33995,
"TEXTURE12": 33996,
"TEXTURE13": 33997,
"TEXTURE14": 33998,
"TEXTURE15": 33999,
"TEXTURE16": 34000,
"TEXTURE17": 34001,
"TEXTURE18": 34002,
"TEXTURE19": 34003,
"TEXTURE20": 34004,
"TEXTURE21": 34005,
"TEXTURE22": 34006,
"TEXTURE23": 34007,
"TEXTURE24": 34008,
"TEXTURE25": 34009,
"TEXTURE26": 34010,
"TEXTURE27": 34011,
"TEXTURE28": 34012,
"TEXTURE29": 34013,
"TEXTURE30": 34014,
"TEXTURE31": 34015,
"ACTIVE_TEXTURE": 34016,
"REPEAT": 10497,
"CLAMP_TO_EDGE": 33071,
"MIRRORED_REPEAT": 33648,
"FLOAT_VEC2": 35664,
"FLOAT_VEC3": 35665,
"FLOAT_VEC4": 35666,
"INT_VEC2": 35667,
"INT_VEC3": 35668,
"INT_VEC4": 35669,
"BOOL": 35670,
"BOOL_VEC2": 35671,
"BOOL_VEC3": 35672,
"BOOL_VEC4": 35673,
"FLOAT_MAT2": 35674,
"FLOAT_MAT3": 35675,
"FLOAT_MAT4": 35676,
"SAMPLER_2D": 35678,
"SAMPLER_CUBE": 35680,
"VERTEX_ATTRIB_ARRAY_ENABLED": 34338,
"VERTEX_ATTRIB_ARRAY_SIZE": 34339,
"VERTEX_ATTRIB_ARRAY_STRIDE": 34340,
"VERTEX_ATTRIB_ARRAY_TYPE": 34341,
"VERTEX_ATTRIB_ARRAY_NORMALIZED": 34922,
"VERTEX_ATTRIB_ARRAY_POINTER": 34373,
"VERTEX_ATTRIB_ARRAY_BUFFER_BINDING": 34975,
"IMPLEMENTATION_COLOR_READ_TYPE": 35738,
"IMPLEMENTATION_COLOR_READ_FORMAT": 35739,
"COMPILE_STATUS": 35713,
"LOW_FLOAT": 36336,
"MEDIUM_FLOAT": 36337,
"HIGH_FLOAT": 36338,
"LOW_INT": 36339,
"MEDIUM_INT": 36340,
"HIGH_INT": 36341,
"FRAMEBUFFER": 36160,
"RENDERBUFFER": 36161,
"RGBA4": 32854,
"RGB5_A1": 32855,
"RGB565": 36194,
"DEPTH_COMPONENT16": 33189,
"STENCIL_INDEX8": 36168,
"DEPTH_STENCIL": 34041,
"RENDERBUFFER_WIDTH": 36162,
"RENDERBUFFER_HEIGHT": 36163,
"RENDERBUFFER_INTERNAL_FORMAT": 36164,
"RENDERBUFFER_RED_SIZE": 36176,
"RENDERBUFFER_GREEN_SIZE": 36177,
"RENDERBUFFER_BLUE_SIZE": 36178,
"RENDERBUFFER_ALPHA_SIZE": 36179,
"RENDERBUFFER_DEPTH_SIZE": 36180,
"RENDERBUFFER_STENCIL_SIZE": 36181,
"FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE": 36048,
"FRAMEBUFFER_ATTACHMENT_OBJECT_NAME": 36049,
"FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL": 36050,
"FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE": 36051,
"COLOR_ATTACHMENT0": 36064,
"DEPTH_ATTACHMENT": 36096,
"STENCIL_ATTACHMENT": 36128,
"DEPTH_STENCIL_ATTACHMENT": 33306,
"NONE": 0,
"FRAMEBUFFER_COMPLETE": 36053,
"FRAMEBUFFER_INCOMPLETE_ATTACHMENT": 36054,
"FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT": 36055,
"FRAMEBUFFER_INCOMPLETE_DIMENSIONS": 36057,
"FRAMEBUFFER_UNSUPPORTED": 36061,
"FRAMEBUFFER_BINDING": 36006,
"RENDERBUFFER_BINDING": 36007,
"MAX_RENDERBUFFER_SIZE": 34024,
"INVALID_FRAMEBUFFER_OPERATION": 1286,
"UNPACK_FLIP_Y_WEBGL": 37440,
"UNPACK_PREMULTIPLY_ALPHA_WEBGL": 37441,
"CONTEXT_LOST_WEBGL": 37442,
"UNPACK_COLORSPACE_CONVERSION_WEBGL": 37443,
"BROWSER_DEFAULT_WEBGL": 37444
};

@ -0,0 +1,142 @@
let i = 1;
const GLmethod = {};
GLmethod.activeTexture = i++; //1
GLmethod.attachShader = i++;
GLmethod.bindAttribLocation = i++;
GLmethod.bindBuffer = i++;
GLmethod.bindFramebuffer = i++;
GLmethod.bindRenderbuffer = i++;
GLmethod.bindTexture = i++;
GLmethod.blendColor = i++;
GLmethod.blendEquation = i++;
GLmethod.blendEquationSeparate = i++; //10
GLmethod.blendFunc = i++;
GLmethod.blendFuncSeparate = i++;
GLmethod.bufferData = i++;
GLmethod.bufferSubData = i++;
GLmethod.checkFramebufferStatus = i++;
GLmethod.clear = i++;
GLmethod.clearColor = i++;
GLmethod.clearDepth = i++;
GLmethod.clearStencil = i++;
GLmethod.colorMask = i++; //20
GLmethod.compileShader = i++;
GLmethod.compressedTexImage2D = i++;
GLmethod.compressedTexSubImage2D = i++;
GLmethod.copyTexImage2D = i++;
GLmethod.copyTexSubImage2D = i++;
GLmethod.createBuffer = i++;
GLmethod.createFramebuffer = i++;
GLmethod.createProgram = i++;
GLmethod.createRenderbuffer = i++;
GLmethod.createShader = i++; //30
GLmethod.createTexture = i++;
GLmethod.cullFace = i++;
GLmethod.deleteBuffer = i++;
GLmethod.deleteFramebuffer = i++;
GLmethod.deleteProgram = i++;
GLmethod.deleteRenderbuffer = i++;
GLmethod.deleteShader = i++;
GLmethod.deleteTexture = i++;
GLmethod.depthFunc = i++;
GLmethod.depthMask = i++; //40
GLmethod.depthRange = i++;
GLmethod.detachShader = i++;
GLmethod.disable = i++;
GLmethod.disableVertexAttribArray = i++;
GLmethod.drawArrays = i++;
GLmethod.drawArraysInstancedANGLE = i++;
GLmethod.drawElements = i++;
GLmethod.drawElementsInstancedANGLE = i++;
GLmethod.enable = i++;
GLmethod.enableVertexAttribArray = i++; //50
GLmethod.flush = i++;
GLmethod.framebufferRenderbuffer = i++;
GLmethod.framebufferTexture2D = i++;
GLmethod.frontFace = i++;
GLmethod.generateMipmap = i++;
GLmethod.getActiveAttrib = i++;
GLmethod.getActiveUniform = i++;
GLmethod.getAttachedShaders = i++;
GLmethod.getAttribLocation = i++;
GLmethod.getBufferParameter = i++; //60
GLmethod.getContextAttributes = i++;
GLmethod.getError = i++;
GLmethod.getExtension = i++;
GLmethod.getFramebufferAttachmentParameter = i++;
GLmethod.getParameter = i++;
GLmethod.getProgramInfoLog = i++;
GLmethod.getProgramParameter = i++;
GLmethod.getRenderbufferParameter = i++;
GLmethod.getShaderInfoLog = i++;
GLmethod.getShaderParameter = i++; //70
GLmethod.getShaderPrecisionFormat = i++;
GLmethod.getShaderSource = i++;
GLmethod.getSupportedExtensions = i++;
GLmethod.getTexParameter = i++;
GLmethod.getUniform = i++;
GLmethod.getUniformLocation = i++;
GLmethod.getVertexAttrib = i++;
GLmethod.getVertexAttribOffset = i++;
GLmethod.isBuffer = i++;
GLmethod.isContextLost = i++; //80
GLmethod.isEnabled = i++;
GLmethod.isFramebuffer = i++;
GLmethod.isProgram = i++;
GLmethod.isRenderbuffer = i++;
GLmethod.isShader = i++;
GLmethod.isTexture = i++;
GLmethod.lineWidth = i++;
GLmethod.linkProgram = i++;
GLmethod.pixelStorei = i++;
GLmethod.polygonOffset = i++; //90
GLmethod.readPixels = i++;
GLmethod.renderbufferStorage = i++;
GLmethod.sampleCoverage = i++;
GLmethod.scissor = i++;
GLmethod.shaderSource = i++;
GLmethod.stencilFunc = i++;
GLmethod.stencilFuncSeparate = i++;
GLmethod.stencilMask = i++;
GLmethod.stencilMaskSeparate = i++;
GLmethod.stencilOp = i++; //100
GLmethod.stencilOpSeparate = i++;
GLmethod.texImage2D = i++;
GLmethod.texParameterf = i++;
GLmethod.texParameteri = i++;
GLmethod.texSubImage2D = i++;
GLmethod.uniform1f = i++;
GLmethod.uniform1fv = i++;
GLmethod.uniform1i = i++;
GLmethod.uniform1iv = i++;
GLmethod.uniform2f = i++; //110
GLmethod.uniform2fv = i++;
GLmethod.uniform2i = i++;
GLmethod.uniform2iv = i++;
GLmethod.uniform3f = i++;
GLmethod.uniform3fv = i++;
GLmethod.uniform3i = i++;
GLmethod.uniform3iv = i++;
GLmethod.uniform4f = i++;
GLmethod.uniform4fv = i++;
GLmethod.uniform4i = i++; //120
GLmethod.uniform4iv = i++;
GLmethod.uniformMatrix2fv = i++;
GLmethod.uniformMatrix3fv = i++;
GLmethod.uniformMatrix4fv = i++;
GLmethod.useProgram = i++;
GLmethod.validateProgram = i++;
GLmethod.vertexAttrib1f = i++; //new
GLmethod.vertexAttrib2f = i++; //new
GLmethod.vertexAttrib3f = i++; //new
GLmethod.vertexAttrib4f = i++; //new //130
GLmethod.vertexAttrib1fv = i++; //new
GLmethod.vertexAttrib2fv = i++; //new
GLmethod.vertexAttrib3fv = i++; //new
GLmethod.vertexAttrib4fv = i++; //new
GLmethod.vertexAttribPointer = i++;
GLmethod.viewport = i++;
export default GLmethod;

@ -0,0 +1,23 @@
const GLtype = {};
[
"GLbitfield",
"GLboolean",
"GLbyte",
"GLclampf",
"GLenum",
"GLfloat",
"GLint",
"GLintptr",
"GLsizei",
"GLsizeiptr",
"GLshort",
"GLubyte",
"GLuint",
"GLushort"
].sort().map((typeName, i) => GLtype[typeName] = 1 >> (i + 1));
export default GLtype;

@ -0,0 +1,21 @@
import {getTransferedObjectUUID} from './classUtils';
const name = 'WebGLProgram';
function uuid(id) {
return getTransferedObjectUUID(name, id);
}
export default class WebGLProgram {
className = name;
constructor(id) {
this.id = id;
}
static uuid = uuid;
uuid() {
return uuid(this.id);
}
}

@ -0,0 +1,21 @@
import {getTransferedObjectUUID} from './classUtils';
const name = 'WebGLRenderBuffer';
function uuid(id) {
return getTransferedObjectUUID(name, id);
}
export default class WebGLRenderbuffer {
className = name;
constructor(id) {
this.id = id;
}
static uuid = uuid;
uuid() {
return uuid(this.id);
}
}

@ -0,0 +1,22 @@
import {getTransferedObjectUUID} from './classUtils';
const name = 'WebGLShader';
function uuid(id) {
return getTransferedObjectUUID(name, id);
}
export default class WebGLShader {
className = name;
constructor(id, type) {
this.id = id;
this.type = type;
}
static uuid = uuid;
uuid() {
return uuid(this.id);
}
}

@ -0,0 +1,11 @@
export default class WebGLShaderPrecisionFormat {
className = 'WebGLShaderPrecisionFormat';
constructor({
rangeMin, rangeMax, precision
}) {
this.rangeMin = rangeMin;
this.rangeMax = rangeMax;
this.precision = precision;
}
}

@ -0,0 +1,22 @@
import {getTransferedObjectUUID} from './classUtils';
const name = 'WebGLTexture';
function uuid(id) {
return getTransferedObjectUUID(name, id);
}
export default class WebGLTexture {
className = name;
constructor(id, type) {
this.id = id;
this.type = type;
}
static uuid = uuid;
uuid() {
return uuid(this.id);
}
}

@ -0,0 +1,22 @@
import {getTransferedObjectUUID} from './classUtils';
const name = 'WebGLUniformLocation';
function uuid(id) {
return getTransferedObjectUUID(name, id);
}
export default class WebGLUniformLocation {
className = name;
constructor(id, type) {
this.id = id;
this.type = type;
}
static uuid = uuid;
uuid() {
return uuid(this.id);
}
}

@ -0,0 +1,3 @@
export function getTransferedObjectUUID(name, id) {
return `${name.toLowerCase()}-${id}`;
}

@ -0,0 +1,74 @@
import GContext2D from '../context-2d/RenderingContext';
import GContextWebGL from '../context-webgl/RenderingContext';
export default class GCanvas {
// static GBridge = null;
id = null;
_needRender = true;
constructor(id, { disableAutoSwap }) {
this.id = id;
this._disableAutoSwap = disableAutoSwap;
if (disableAutoSwap) {
this._swapBuffers = () => {
GCanvas.GBridge.render(this.id);
}
}
}
getContext(type) {
let context = null;
if (type.match(/webgl/i)) {
context = new GContextWebGL(this);
context.componentId = this.id;
if (!this._disableAutoSwap) {
const render = () => {
if (this._needRender) {
GCanvas.GBridge.render(this.id);
this._needRender = false;
}
}
setInterval(render, 16);
}
GCanvas.GBridge.callSetContextType(this.id, 1); // 0 for 2d; 1 for webgl
} else if (type.match(/2d/i)) {
context = new GContext2D(this);
context.componentId = this.id;
// const render = ( callback ) => {
//
// const commands = context._drawCommands;
// context._drawCommands = '';
//
// GCanvas.GBridge.render2d(this.id, commands, callback);
// this._needRender = false;
// }
// //draw方法触发
// context._flush = render;
// //setInterval(render, 16);
GCanvas.GBridge.callSetContextType(this.id, 0);
} else {
throw new Error('not supported context ' + type);
}
return context;
}
reset() {
GCanvas.GBridge.callReset(this.id);
}
}

@ -0,0 +1,96 @@
let incId = 1;
const noop = function () { };
class GImage {
static GBridge = null;
constructor() {
this._id = incId++;
this._width = 0;
this._height = 0;
this._src = undefined;
this._onload = noop;
this._onerror = noop;
this.complete = false;
}
get width() {
return this._width;
}
set width(v) {
this._width = v;
}
get height() {
return this._height;
}
set height(v) {
this._height = v;
}
get src() {
return this._src;
}
set src(v) {
if (v.startsWith('//')) {
v = 'http:' + v;
}
this._src = v;
GImage.GBridge.perloadImage([this._src, this._id], (data) => {
if (typeof data === 'string') {
data = JSON.parse(data);
}
if (data.error) {
var evt = { type: 'error', target: this };
this.onerror(evt);
} else {
this.complete = true;
this.width = typeof data.width === 'number' ? data.width : 0;
this.height = typeof data.height === 'number' ? data.height : 0;
var evt = { type: 'load', target: this };
this.onload(evt);
}
});
}
addEventListener(name, listener) {
if (name === 'load') {
this.onload = listener;
} else if (name === 'error') {
this.onerror = listener;
}
}
removeEventListener(name, listener) {
if (name === 'load') {
this.onload = noop;
} else if (name === 'error') {
this.onerror = noop;
}
}
get onload() {
return this._onload;
}
set onload(v) {
this._onload = v;
}
get onerror() {
return this._onerror;
}
set onerror(v) {
this._onerror = v;
}
}
export default GImage;

@ -0,0 +1,24 @@
export function ArrayBufferToBase64 (buffer) {
var binary = '';
var bytes = new Uint8ClampedArray(buffer);
for (var len = bytes.byteLength, i = 0; i < len; i++) {
binary += String.fromCharCode(bytes[i]);
}
return btoa(binary);
}
export function Base64ToUint8ClampedArray(base64String) {
const padding = '='.repeat((4 - base64String.length % 4) % 4);
const base64 = (base64String + padding)
.replace(/\-/g, '+')
.replace(/_/g, '/');
const rawData = atob(base64);
const outputArray = new Uint8ClampedArray(rawData.length);
for (let i = 0; i < rawData.length; ++i) {
outputArray[i] = rawData.charCodeAt(i);
}
return outputArray;
}

@ -0,0 +1,39 @@
import GCanvas from './env/canvas';
import GImage from './env/image';
import GWebGLRenderingContext from './context-webgl/RenderingContext';
import GContext2D from './context-2d/RenderingContext';
import GBridgeWeex from './bridge/bridge-weex';
export let Image = GImage;
export let WeexBridge = GBridgeWeex;
export function enable(el, { bridge, debug, disableAutoSwap, disableComboCommands } = {}) {
const GBridge = GImage.GBridge = GCanvas.GBridge = GWebGLRenderingContext.GBridge = GContext2D.GBridge = bridge;
GBridge.callEnable(el.ref, [
0, // renderMode: 0--RENDERMODE_WHEN_DIRTY, 1--RENDERMODE_CONTINUOUSLY
-1, // hybridLayerType: 0--LAYER_TYPE_NONE 1--LAYER_TYPE_SOFTWARE 2--LAYER_TYPE_HARDWARE
false, // supportScroll
false, // newCanvasMode
1, // compatible
'white',// clearColor
false // sameLevel: newCanvasMode = true && true => GCanvasView and Webview is same level
]);
if (debug === true) {
GBridge.callEnableDebug();
}
if (disableComboCommands) {
GBridge.callEnableDisableCombo();
}
var canvas = new GCanvas(el.ref, { disableAutoSwap });
canvas.width = el.style.width;
canvas.height = el.style.height;
return canvas;
};

File diff suppressed because one or more lines are too long

@ -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.

File diff suppressed because it is too large Load Diff

@ -0,0 +1,24 @@
{
"name": "u-qrcode",
"version": "3.2.2",
"description": "uQRCode 二维码生成插件",
"main": "u-qrcode.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/Sansnn/uQRCode.git"
},
"keywords": [
"QR",
"QRCode",
"uQRCode"
],
"author": "Sansnn",
"license": "Apache-2.0",
"bugs": {
"url": "https://github.com/Sansnn/uQRCode/issues"
},
"homepage": "https://github.com/Sansnn/uQRCode#readme"
}

@ -0,0 +1,274 @@
# uQRCode
**点击群号加入群聊【uQRCode交流群】:[695070434](https://jq.qq.com/?_wv=1027&k=JRjzDqiw)**
uQRCode 生成方式简单,可扩展性高,适用所有前端应用和Node.js服务端,可运行到所有支持canvas的平台。支持NVUE(NVUE中使用GCanvas)。
支持自定义二维码渲染规则,可通过uQRCode API得到矩阵信息后,自行实现canvas或view+css渲染二维码,如随机颜色、圆点、方块、块与块之间的间距等,详情参考示例项目。
### 插件市场
[https://ext.dcloud.net.cn/plugin?id=1287](https://ext.dcloud.net.cn/plugin?id=1287)
### github
[https://github.com/Sansnn/uQRCode](https://github.com/Sansnn/uQRCode)
### npm
[https://www.npmjs.com/package/u-qrcode](https://www.npmjs.com/package/u-qrcode)
### 示例预览
[https://static-c15f4b57-ef97-4d2b-b939-f580f910d7e2.bspapp.com](https://static-c15f4b57-ef97-4d2b-b939-f580f910d7e2.bspapp.com)
### 二维码
**什么是QR码**
QR码属于矩阵式二维码中的一个种类,由DENSO(日本电装)公司开发,由JIS和ISO将其标准化。
**QR码的特点**
一是高速读取(QR就是取自“Quick Response”的首字母),通过摄像头从拍摄到解码到显示内容也就三秒左右,对摄像的角度也没有什么要求;
二是高容量、高密度,理论上内容经过压缩处理后可以存7089个数字,4296个字母和数字混合字符,2953个8位字节数据,1817个汉字;
三是支持纠错处理,按照QR码的标准文档说明,QR码的纠错分为4个级别,分别是:
- level L : 最大 7% 的错误能够被纠正;
- level M : 最大 15% 的错误能够被纠正;
- level Q : 最大 25% 的错误能够被纠正;
- level H : 最大 30% 的错误能够被纠正;
四是结构化,看似无规则的图形,其实对区域有严格的定义。
更多二维码介绍及原理:[https://blog.csdn.net/jason_ldh/article/details/11801355](https://blog.csdn.net/jason_ldh/article/details/11801355)
### 组件使用
导入`u-qrcode`组件后,在 `template` 中创建 `<u-qrcode/>` 组件
```html
<u-qrcode ref="qrcode" canvas-id="qrcode" value="uQRCode"></u-qrcode>
```
### 属性说明
|属性名 |类型 |可选值 |默认值 |是否必填 |说明 |
|--- |--- |--- |--- |--- |:--- |
|canvasId |String |- |- |是 |组件标识/canvasId |
|value |String |- |- |是 |二维码内容 |
|size |Number |- |354 |否 |二维码大小,默认单位px,rpx需要使用uni.upx2px()转换|
|options |Object |- |- |否 |参数可选项,详见下方options说明 |
### 事件说明
|事件名 |参数 |返回值 |说明 |
|--- |--- |--- |:--- |
|click |- |void |点击事件 |
|complete |- |Object |生成完成事件,返回值success: true表示生成成功,false生成失败 |
### 方法说明
|方法名 |参数 |返回值 |说明 |
|--- |--- |--- |:--- |
|remake |- |void |重新生成 |
|toTempFilePath |Object:callback|void |导出临时路径 |
|save |Object:callback|void |保存 |
#### options说明
|属性名 |类型 |可选值 |默认值 |是否必填 |说明 |
|--- |--- |--- |--- |--- |:--- |
|typeNumber |Number |- |-1 |否 |二维码版本 |
|errorCorrectLevel |String/Number|L/M/Q/H/1/0/3/2|H |否 |纠错等级L/M/Q/H分别对应1/0/3/2 |
|useDynamicSize |Boolean |- |false |否 |是否使用动态尺寸,可以去除二维码小块白色细线 |
|margin |Number |- |0 |否 |填充边距,默认单位px |
|background |Object |- |- |否 |背景设置,详见下方options.background说明 |
|foreground |Object |- |- |否 |前景设置,详见下方options.foreground说明 |
|positionDetection |Object |- |- |否 |定位角设置,详见下方options.positionDetection说明 |
|separator |Object |- |- |否 |分割图案设置,详见下方options.separator说明 |
|alignment |Object |- |- |否 |对齐图案设置,详见下方options.alignment说明 |
|timing |Object |- |- |否 |时序图案设置,详见下方options.timing说明 |
|darkBlock |Object |- |- |否 |暗块设置,详见下方options.darkBlock说明 |
|versionInformation |Object |- |- |否 |版本信息设置,详见下方options.versionInformation说明 |
#### options.background说明
|属性名 |类型 |可选值 |默认值 |是否必填 |说明 |
|--- |--- |--- |--- |--- |:--- |
|color |String |- |#FFFFFF|否 |背景色,若需要透明背景可设置为rgba(0,0,0,0)|
|image |Object |- |- |否 |背景图片设置,详见下方options.background.image说明|
#### options.background.image说明
|属性名 |类型 |可选值 |默认值 |是否必填 |说明 |
|--- |--- |--- |--- |--- |:--- |
|src |String |- |- |否 |背景图片路径 |
|width |Number |- |1 |否 |指定背景图片宽度,1为二维码size的100% |
|height |Number |- |1 |否 |指定背景图片高度,1为二维码size的100% |
|align |Array<String>|['left'/'center'/'right', 'top'/'center'/'bottom'] |['center', 'center'] |否 |指定背景图片对齐方式,[0]为水平方位,[1]为垂直方位 |
|anchor |Array<Number>|- |[0, 0] |否 |指定背景图片锚点,[0]为X轴偏移量,[1]为Y轴偏移量 |
|alpha |Number |0-1 |1 |否 |指定背景图片透明度 |
#### options.foreground说明
|属性名 |类型 |可选值 |默认值 |是否必填 |说明 |
|--- |--- |--- |--- |--- |:--- |
|color |String |- |#FFFFFF|否 |前景色 |
|image |Object |- |- |否 |前景图片设置,详见下方options.foreground.image说明 |
#### options.foreground.image说明
|属性名 |类型 |可选值 |默认值 |是否必填 |说明 |
|--- |--- |--- |--- |--- |:--- |
|src |String |- |- |否 |前景图片路径 |
|width |Number |- |1/4 |否 |指定前景图片宽度,1为二维码size的100% |
|height |Number |- |1/4 |否 |指定前景图片高度,1为二维码size的100% |
|align |Array<String>|['left'/'center'/'right', 'top'/'center'/'bottom'] |['center', 'center'] |否 |指定前景图片对齐方式,[0]为水平方位,[1]为垂直方位 |
|anchor |Array<Number>|- |[0, 0] |否 |指定前景图片锚点,[0]为X轴偏移量,[1]为Y轴偏移量 |
#### options.positionDetection说明
|属性名 |类型 |可选值 |默认值 |是否必填 |说明 |
|--- |--- |--- |--- |--- |:--- |
|backgroundColor|String |- |options.background.color |否 |定位角区域背景色,默认值跟随背景色 |
|foregroundColor|String |- |options.foreground.color |否 |定位角小块颜色,默认值跟随前景色 |
#### options.separator说明
|属性名 |类型 |可选值 |默认值 |是否必填 |说明 |
|--- |--- |--- |--- |--- |:--- |
|color |String |- |options.background.color |否 |分割区域颜色,默认值跟随背景色 |
#### options.alignment说明
|属性名 |类型 |可选值 |默认值 |是否必填 |说明 |
|--- |--- |--- |--- |--- |:--- |
|backgroundColor|String |- |options.background.color |否 |对齐区域背景色,默认值跟随背景色 |
|foregroundColor|String |- |options.foreground.color |否 |对齐小块颜色,默认值跟随前景色 |
#### options.timing说明
|属性名 |类型 |可选值 |默认值 |是否必填 |说明 |
|--- |--- |--- |--- |--- |:--- |
|backgroundColor|String |- |options.background.color |否 |时序区域背景色,默认值跟随背景色 |
|foregroundColor|String |- |options.foreground.color |否 |时序小块颜色,默认值跟随前景色 |
#### options.darkBlock说明
|属性名 |类型 |可选值 |默认值 |是否必填 |说明 |
|--- |--- |--- |--- |--- |:--- |
|color |String |- |options.foreground.color |否 |暗块颜色,默认值跟随前景色 |
#### options.versionInformation说明
|属性名 |类型 |可选值 |默认值 |是否必填 |说明 |
|--- |--- |--- |--- |--- |:--- |
|backgroundColor|String |- |options.background.color |否 |版本信息区域背景色,默认值跟随背景色 |
|foregroundColor|String |- |options.foreground.color |否 |版本信息小块颜色,默认值跟随前景色 |
### u-qrcode.js使用
引入u-qrcode.js
``` javascript
import uQRCode from '../../uni_modules/Sansnn-uQRCode/js_sdk/u-qrcode';
```
或者使用npm安装
> npm i u-qrcode
``` javascript
import uQRCode from 'u-qrcode';
```
nodejs引入
``` javascript
import uQRCode from 'u-qrcode/module';
```
`template` 中创建 `<canvas/>` 组件并设置 `id`,画布宽高
```html
<canvas id="qrcode" canvas-id="qrcode" :style="{ width: `${size}px`, height: `${size}px` }"></canvas>
```
`script` 中调用生成方法
```javascript
import uQRCode from '../../uni_modules/Sansnn-uQRCode/js_sdk/u-qrcode';
export default {
data() {
return {
text: 'uQRCode',
size: 256
}
},
onReady() {
const ctx = uni.createCanvasContext('qrcode');
const uqrcode = new uQRCode(
{
text: this.text,
size: this.size
},
ctx
);
uqrcode.make();
uqrcode.draw();
}
}
```
### new uQRCode(options, canvasContext, loadImage)说明
|属性名 |类型 |可选值 |默认值 |是否必填 |说明 |
|--- |--- |--- |--- |--- |:--- |
|options |Object |- |- |是 |包含组件属性中的options的所有属性,详见下方options说明 |
|canvasContext|Object |- |- |是 |canvas绘画上下文 |
|loadImage |Promise|- |- |否 |绘制图片时,某些平台必传,例如微信小程序2d绘图需要创建Image对象,不能直接使用路径,这时就需要传入canvas.createImage给loadImage方法,否则无法绘制图片 |
#### options说明,包含组件属性中的options的所有属性,下方仅列举未包含的属性,其余属性请移步到组件属性options说明查看
|属性名 |类型 |可选值 |默认值 |是否必填 |说明 |
|--- |--- |--- |--- |--- |:--- |
|text |String |- |- |是 |二维码内容 |
|size |Number |- |354 |否 |二维码大小 |
### uQRCode实例属性
|属性名 |类型 |说明 |
|--- |--- |:--- |
|options |Object |实例化传入的选项值 |
|canvasContext|Object |画布实例 |
|makeData |Object |制作二维码全部数据 |
|modules |Array |制作二维码主要模块数据 |
|moduleCount |Number |模块数量 |
### uQRCode实例方法
|方法名 |参数 |返回值 |说明 |
|--- |--- |--- |:--- |
|make |- |void |制作二维码方法 |
|draw |options|Promise|绘制二维码方法,绘制层级关系,最底层背景 -> 背景图片 -> 前景 -> 最顶层前景图片,options见下方说明 |
#### draw(options)说明
|属性名 |类型 |可选值 |默认值 |是否必填 |说明 |
|--- |--- |--- |--- |--- |:--- |
|drawBackground |Object: {before, after}|- |- |否 |绘制背景前后可执行自定义方法before,after |
|drawBackgroundImage|Object: {before, after}|- |- |否 |绘制背景图前后可执行自定义方法before,after|
|drawForeground |Object: {before, after}|- |- |否 |绘制前景前后可执行自定义方法before,after |
|drawForegroundImage|Object: {before, after}|- |- |否 |绘制前景图前后可执行自定义方法before,after|
### uQRCode静态属性
|属性名 |类型 |说明 |
|--- |--- |:--- |
|errorCorrectLevel|Object |纠错等级 |
|defaults |Object |预设默认值 |
### uQRCode静态方法
|方法名 |参数 |返回值 |说明 |
|--- |--- |--- |:--- |
|deepReplace|o, r |替换后的新对象 |对象属性深度替换 |
### 常见问题
**如何扫码跳转指定网页**
二维码内容直接放入完整的网页地址即可,例如:`https://ext.dcloud.net.cn/plugin?id=1287`。微信客户端不能是ip地址。
**nvue打包后生成失败**
Canvas是作为独立的模块,打包时需要选择使用Canvas模块才能正常使用相关的功能。 需要在manifest.json的代码视图中配置如下(暂时还不支持可视化界面操作):
```javascript
"app-plus" : {
/* 模块配置 */
"modules" : {
"Canvas" : "nvue canvas" //使用Canvas模块
},
//...
},
//...
```
保存好提交云端打包。

File diff suppressed because it is too large Load Diff

@ -0,0 +1,83 @@
{
"id": "Sansnn-uQRCode",
"displayName": "uQRCode 二维码生成插件 支持nvue 支持nodejs服务端",
"version": "3.2.2",
"description": "uQRCode 是一款使用方式简单,高扩展的二维码生成插件。支持全端生成,支持canvas的地方就可以使用uQRCode。",
"keywords": [
"uQRCode",
"二维码",
"qrcode",
"qr"
],
"repository": "https://github.com/Sansnn/uQRCode",
"engines": {
"HBuilderX": "^3.1.0"
},
"dcloudext": {
"category": [
"JS SDK",
"通用 SDK"
],
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": "https://www.npmjs.com/package/u-qrcode"
},
"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"
}
}
}
}
}

@ -0,0 +1,274 @@
# uQRCode
**点击群号加入群聊【uQRCode交流群】:[695070434](https://jq.qq.com/?_wv=1027&k=JRjzDqiw)**
uQRCode 生成方式简单,可扩展性高,适用所有前端应用和Node.js服务端,可运行到所有支持canvas的平台。支持NVUE(NVUE中使用GCanvas)。
支持自定义二维码渲染规则,可通过uQRCode API得到矩阵信息后,自行实现canvas或view+css渲染二维码,如随机颜色、圆点、方块、块与块之间的间距等,详情参考示例项目。
### 插件市场
[https://ext.dcloud.net.cn/plugin?id=1287](https://ext.dcloud.net.cn/plugin?id=1287)
### github
[https://github.com/Sansnn/uQRCode](https://github.com/Sansnn/uQRCode)
### npm
[https://www.npmjs.com/package/u-qrcode](https://www.npmjs.com/package/u-qrcode)
### 示例预览
[https://static-c15f4b57-ef97-4d2b-b939-f580f910d7e2.bspapp.com](https://static-c15f4b57-ef97-4d2b-b939-f580f910d7e2.bspapp.com)
### 二维码
**什么是QR码**
QR码属于矩阵式二维码中的一个种类,由DENSO(日本电装)公司开发,由JIS和ISO将其标准化。
**QR码的特点**
一是高速读取(QR就是取自“Quick Response”的首字母),通过摄像头从拍摄到解码到显示内容也就三秒左右,对摄像的角度也没有什么要求;
二是高容量、高密度,理论上内容经过压缩处理后可以存7089个数字,4296个字母和数字混合字符,2953个8位字节数据,1817个汉字;
三是支持纠错处理,按照QR码的标准文档说明,QR码的纠错分为4个级别,分别是:
- level L : 最大 7% 的错误能够被纠正;
- level M : 最大 15% 的错误能够被纠正;
- level Q : 最大 25% 的错误能够被纠正;
- level H : 最大 30% 的错误能够被纠正;
四是结构化,看似无规则的图形,其实对区域有严格的定义。
更多二维码介绍及原理:[https://blog.csdn.net/jason_ldh/article/details/11801355](https://blog.csdn.net/jason_ldh/article/details/11801355)
### 组件使用
导入`u-qrcode`组件后,在 `template` 中创建 `<u-qrcode/>` 组件
```html
<u-qrcode ref="qrcode" canvas-id="qrcode" value="uQRCode"></u-qrcode>
```
### 属性说明
|属性名 |类型 |可选值 |默认值 |是否必填 |说明 |
|--- |--- |--- |--- |--- |:--- |
|canvasId |String |- |- |是 |组件标识/canvasId |
|value |String |- |- |是 |二维码内容 |
|size |Number |- |354 |否 |二维码大小,默认单位px,rpx需要使用uni.upx2px()转换|
|options |Object |- |- |否 |参数可选项,详见下方options说明 |
### 事件说明
|事件名 |参数 |返回值 |说明 |
|--- |--- |--- |:--- |
|click |- |void |点击事件 |
|complete |- |Object |生成完成事件,返回值success: true表示生成成功,false生成失败 |
### 方法说明
|方法名 |参数 |返回值 |说明 |
|--- |--- |--- |:--- |
|remake |- |void |重新生成 |
|toTempFilePath |Object:callback|void |导出临时路径 |
|save |Object:callback|void |保存 |
#### options说明
|属性名 |类型 |可选值 |默认值 |是否必填 |说明 |
|--- |--- |--- |--- |--- |:--- |
|typeNumber |Number |- |-1 |否 |二维码版本 |
|errorCorrectLevel |String/Number|L/M/Q/H/1/0/3/2|H |否 |纠错等级L/M/Q/H分别对应1/0/3/2 |
|useDynamicSize |Boolean |- |false |否 |是否使用动态尺寸,可以去除二维码小块白色细线 |
|margin |Number |- |0 |否 |填充边距,默认单位px |
|background |Object |- |- |否 |背景设置,详见下方options.background说明 |
|foreground |Object |- |- |否 |前景设置,详见下方options.foreground说明 |
|positionDetection |Object |- |- |否 |定位角设置,详见下方options.positionDetection说明 |
|separator |Object |- |- |否 |分割图案设置,详见下方options.separator说明 |
|alignment |Object |- |- |否 |对齐图案设置,详见下方options.alignment说明 |
|timing |Object |- |- |否 |时序图案设置,详见下方options.timing说明 |
|darkBlock |Object |- |- |否 |暗块设置,详见下方options.darkBlock说明 |
|versionInformation |Object |- |- |否 |版本信息设置,详见下方options.versionInformation说明 |
#### options.background说明
|属性名 |类型 |可选值 |默认值 |是否必填 |说明 |
|--- |--- |--- |--- |--- |:--- |
|color |String |- |#FFFFFF|否 |背景色,若需要透明背景可设置为rgba(0,0,0,0)|
|image |Object |- |- |否 |背景图片设置,详见下方options.background.image说明|
#### options.background.image说明
|属性名 |类型 |可选值 |默认值 |是否必填 |说明 |
|--- |--- |--- |--- |--- |:--- |
|src |String |- |- |否 |背景图片路径 |
|width |Number |- |1 |否 |指定背景图片宽度,1为二维码size的100% |
|height |Number |- |1 |否 |指定背景图片高度,1为二维码size的100% |
|align |Array<String>|['left'/'center'/'right', 'top'/'center'/'bottom'] |['center', 'center'] |否 |指定背景图片对齐方式,[0]为水平方位,[1]为垂直方位 |
|anchor |Array<Number>|- |[0, 0] |否 |指定背景图片锚点,[0]为X轴偏移量,[1]为Y轴偏移量 |
|alpha |Number |0-1 |1 |否 |指定背景图片透明度 |
#### options.foreground说明
|属性名 |类型 |可选值 |默认值 |是否必填 |说明 |
|--- |--- |--- |--- |--- |:--- |
|color |String |- |#FFFFFF|否 |前景色 |
|image |Object |- |- |否 |前景图片设置,详见下方options.foreground.image说明 |
#### options.foreground.image说明
|属性名 |类型 |可选值 |默认值 |是否必填 |说明 |
|--- |--- |--- |--- |--- |:--- |
|src |String |- |- |否 |前景图片路径 |
|width |Number |- |1/4 |否 |指定前景图片宽度,1为二维码size的100% |
|height |Number |- |1/4 |否 |指定前景图片高度,1为二维码size的100% |
|align |Array<String>|['left'/'center'/'right', 'top'/'center'/'bottom'] |['center', 'center'] |否 |指定前景图片对齐方式,[0]为水平方位,[1]为垂直方位 |
|anchor |Array<Number>|- |[0, 0] |否 |指定前景图片锚点,[0]为X轴偏移量,[1]为Y轴偏移量 |
#### options.positionDetection说明
|属性名 |类型 |可选值 |默认值 |是否必填 |说明 |
|--- |--- |--- |--- |--- |:--- |
|backgroundColor|String |- |options.background.color |否 |定位角区域背景色,默认值跟随背景色 |
|foregroundColor|String |- |options.foreground.color |否 |定位角小块颜色,默认值跟随前景色 |
#### options.separator说明
|属性名 |类型 |可选值 |默认值 |是否必填 |说明 |
|--- |--- |--- |--- |--- |:--- |
|color |String |- |options.background.color |否 |分割区域颜色,默认值跟随背景色 |
#### options.alignment说明
|属性名 |类型 |可选值 |默认值 |是否必填 |说明 |
|--- |--- |--- |--- |--- |:--- |
|backgroundColor|String |- |options.background.color |否 |对齐区域背景色,默认值跟随背景色 |
|foregroundColor|String |- |options.foreground.color |否 |对齐小块颜色,默认值跟随前景色 |
#### options.timing说明
|属性名 |类型 |可选值 |默认值 |是否必填 |说明 |
|--- |--- |--- |--- |--- |:--- |
|backgroundColor|String |- |options.background.color |否 |时序区域背景色,默认值跟随背景色 |
|foregroundColor|String |- |options.foreground.color |否 |时序小块颜色,默认值跟随前景色 |
#### options.darkBlock说明
|属性名 |类型 |可选值 |默认值 |是否必填 |说明 |
|--- |--- |--- |--- |--- |:--- |
|color |String |- |options.foreground.color |否 |暗块颜色,默认值跟随前景色 |
#### options.versionInformation说明
|属性名 |类型 |可选值 |默认值 |是否必填 |说明 |
|--- |--- |--- |--- |--- |:--- |
|backgroundColor|String |- |options.background.color |否 |版本信息区域背景色,默认值跟随背景色 |
|foregroundColor|String |- |options.foreground.color |否 |版本信息小块颜色,默认值跟随前景色 |
### u-qrcode.js使用
引入u-qrcode.js
``` javascript
import uQRCode from '../../uni_modules/Sansnn-uQRCode/js_sdk/u-qrcode';
```
或者使用npm安装
> npm i u-qrcode
``` javascript
import uQRCode from 'u-qrcode';
```
nodejs引入
``` javascript
import uQRCode from 'u-qrcode/module';
```
`template` 中创建 `<canvas/>` 组件并设置 `id`,画布宽高
```html
<canvas id="qrcode" canvas-id="qrcode" :style="{ width: `${size}px`, height: `${size}px` }"></canvas>
```
`script` 中调用生成方法
```javascript
import uQRCode from '../../uni_modules/Sansnn-uQRCode/js_sdk/u-qrcode';
export default {
data() {
return {
text: 'uQRCode',
size: 256
}
},
onReady() {
const ctx = uni.createCanvasContext('qrcode');
const uqrcode = new uQRCode(
{
text: this.text,
size: this.size
},
ctx
);
uqrcode.make();
uqrcode.draw();
}
}
```
### new uQRCode(options, canvasContext, loadImage)说明
|属性名 |类型 |可选值 |默认值 |是否必填 |说明 |
|--- |--- |--- |--- |--- |:--- |
|options |Object |- |- |是 |包含组件属性中的options的所有属性,详见下方options说明 |
|canvasContext|Object |- |- |是 |canvas绘画上下文 |
|loadImage |Promise|- |- |否 |绘制图片时,某些平台必传,例如微信小程序2d绘图需要创建Image对象,不能直接使用路径,这时就需要传入canvas.createImage给loadImage方法,否则无法绘制图片 |
#### options说明,包含组件属性中的options的所有属性,下方仅列举未包含的属性,其余属性请移步到组件属性options说明查看
|属性名 |类型 |可选值 |默认值 |是否必填 |说明 |
|--- |--- |--- |--- |--- |:--- |
|text |String |- |- |是 |二维码内容 |
|size |Number |- |354 |否 |二维码大小 |
### uQRCode实例属性
|属性名 |类型 |说明 |
|--- |--- |:--- |
|options |Object |实例化传入的选项值 |
|canvasContext|Object |画布实例 |
|makeData |Object |制作二维码全部数据 |
|modules |Array |制作二维码主要模块数据 |
|moduleCount |Number |模块数量 |
### uQRCode实例方法
|方法名 |参数 |返回值 |说明 |
|--- |--- |--- |:--- |
|make |- |void |制作二维码方法 |
|draw |options|Promise|绘制二维码方法,绘制层级关系,最底层背景 -> 背景图片 -> 前景 -> 最顶层前景图片,options见下方说明 |
#### draw(options)说明
|属性名 |类型 |可选值 |默认值 |是否必填 |说明 |
|--- |--- |--- |--- |--- |:--- |
|drawBackground |Object: {before, after}|- |- |否 |绘制背景前后可执行自定义方法before,after |
|drawBackgroundImage|Object: {before, after}|- |- |否 |绘制背景图前后可执行自定义方法before,after|
|drawForeground |Object: {before, after}|- |- |否 |绘制前景前后可执行自定义方法before,after |
|drawForegroundImage|Object: {before, after}|- |- |否 |绘制前景图前后可执行自定义方法before,after|
### uQRCode静态属性
|属性名 |类型 |说明 |
|--- |--- |:--- |
|errorCorrectLevel|Object |纠错等级 |
|defaults |Object |预设默认值 |
### uQRCode静态方法
|方法名 |参数 |返回值 |说明 |
|--- |--- |--- |:--- |
|deepReplace|o, r |替换后的新对象 |对象属性深度替换 |
### 常见问题
**如何扫码跳转指定网页**
二维码内容直接放入完整的网页地址即可,例如:`https://ext.dcloud.net.cn/plugin?id=1287`。微信客户端不能是ip地址。
**nvue打包后生成失败**
Canvas是作为独立的模块,打包时需要选择使用Canvas模块才能正常使用相关的功能。 需要在manifest.json的代码视图中配置如下(暂时还不支持可视化界面操作):
```javascript
"app-plus" : {
/* 模块配置 */
"modules" : {
"Canvas" : "nvue canvas" //使用Canvas模块
},
//...
},
//...
```
保存好提交云端打包。
Loading…
Cancel
Save