Merge branch 'test' of https://e.coding.net/g-cphe0354/duanju/new_app into gaohao
This commit is contained in:
commit
6e6299c341
|
|
@ -2,8 +2,12 @@
|
|||
"version" : "1.0",
|
||||
"configurations" : [
|
||||
{
|
||||
"playground" : "standard",
|
||||
"playground" : "custom",
|
||||
"type" : "uni-app:app-android"
|
||||
},
|
||||
{
|
||||
"playground" : "standard",
|
||||
"type" : "uni-app:app-ios"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
7
App.vue
7
App.vue
|
|
@ -31,7 +31,8 @@ export default {
|
|||
|
||||
<style lang="scss">
|
||||
/*每个页面公共css */
|
||||
@import 'uview-plus/index.scss';
|
||||
@import "uview-plus/index.scss";
|
||||
@import "@/commons/style/common.scss";
|
||||
|
||||
ul,
|
||||
li {
|
||||
|
|
@ -39,11 +40,11 @@ li {
|
|||
}
|
||||
|
||||
.show {
|
||||
display: none !important;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: block !important;
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
page,
|
||||
|
|
|
|||
|
|
@ -7,3 +7,62 @@ export function getVideoDetail(data) {
|
|||
data
|
||||
})
|
||||
}
|
||||
//追剧
|
||||
export function zhuiju(data) {
|
||||
return http.request({
|
||||
url: 'courseCollect/insertCourseCollect',
|
||||
method:'POST',
|
||||
data:{
|
||||
classify:1,
|
||||
...data
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//点赞
|
||||
export function dianzan(data) {
|
||||
return http.request({
|
||||
url: 'courseCollect/insertCourseCollect',
|
||||
method:'POST',
|
||||
data:{
|
||||
classify:3,
|
||||
...data
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//插入播放历史记录
|
||||
|
||||
export function insertHistory(data){
|
||||
return http.request({
|
||||
url: 'courseCollect/insertCourseCollect',
|
||||
method:'POST',
|
||||
data:{
|
||||
classify:3,
|
||||
type:1,
|
||||
...data
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//获取金币比例
|
||||
export function getJinbiBili(data) {
|
||||
return http.request({
|
||||
url: 'common/type/914',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
//获取推荐视频
|
||||
export function tuijianVideo(data){
|
||||
const randomNum=5+ Math.ceil(Math.random()*30)
|
||||
return http.request({
|
||||
url: 'course/selectCourseDetailsList',
|
||||
method:'GET',
|
||||
data:{
|
||||
page: 1,
|
||||
limit: 5,
|
||||
randomNum: randomNum
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
export default{
|
||||
main:'#ff7581'
|
||||
}
|
||||
|
|
@ -0,0 +1,409 @@
|
|||
.u-relative,
|
||||
.u-rela {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.u-absolute,
|
||||
.u-abso {
|
||||
position: absolute;
|
||||
}
|
||||
.u-fixed,.u-fix{
|
||||
position: fixed;
|
||||
}
|
||||
.left-top{
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
.u-overflow-hide{
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
// nvue不能用标签命名样式,不能放在微信组件中,否则微信开发工具会报警告,无法使用标签名当做选择器
|
||||
/* #ifndef APP-NVUE */
|
||||
image {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
// 在weex,也即nvue中,所有元素默认为border-box
|
||||
view,
|
||||
text {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
/* #endif */
|
||||
|
||||
.u-font-xs {
|
||||
font-size: 22rpx;
|
||||
}
|
||||
|
||||
.u-font-sm {
|
||||
font-size: 26rpx;
|
||||
}
|
||||
|
||||
.u-font-md {
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.u-font-lg {
|
||||
font-size: 30rpx;
|
||||
}
|
||||
|
||||
.u-font-xl {
|
||||
font-size: 34rpx;
|
||||
}
|
||||
|
||||
.u-flex {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.u-flex-wrap {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.u-flex-nowrap {
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
|
||||
.u-col-center {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.u-col-top {
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.u-col-bottom {
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.u-row-center {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.u-row-left {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.u-row-right {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.u-row-between {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.u-row-around {
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
.u-text-left {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.u-text-center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.u-text-right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.u-flex-col {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex!important;
|
||||
/* #endif */
|
||||
flex-direction: column!important;
|
||||
}
|
||||
|
||||
// 定义flex等分
|
||||
@for $i from 0 through 12 {
|
||||
.u-flex-#{$i} {
|
||||
flex: $i;
|
||||
}
|
||||
}
|
||||
|
||||
// 定义字体(px)单位,小于20都为px单位字体
|
||||
@for $i from 9 to 20 {
|
||||
.u-font-#{$i} {
|
||||
font-size: $i + px;
|
||||
}
|
||||
}
|
||||
|
||||
// 定义字体(rpx)单位,大于或等于20的都为rpx单位字体
|
||||
@for $i from 20 through 40 {
|
||||
.u-font-#{$i} {
|
||||
font-size: $i + rpx;
|
||||
}
|
||||
}
|
||||
|
||||
// 定义内外边距,历遍1-80
|
||||
@for $i from 0 through 80 {
|
||||
// 只要双数和能被5除尽的数
|
||||
@if $i % 2 == 0 or $i % 5 == 0 {
|
||||
// 得出:u-margin-30或者u-m-30
|
||||
.u-margin-#{$i}, .u-m-#{$i} {
|
||||
margin: $i + rpx!important;
|
||||
}
|
||||
|
||||
// 得出:u-padding-30或者u-p-30
|
||||
.u-padding-#{$i}, .u-p-#{$i} {
|
||||
padding: $i + rpx!important;
|
||||
}
|
||||
|
||||
@each $short, $long in l left, t top, r right, b bottom {
|
||||
// 缩写版,结果如: u-m-l-30
|
||||
// 定义外边距
|
||||
.u-m-#{$short}-#{$i} {
|
||||
margin-#{$long}: $i + rpx!important;
|
||||
}
|
||||
|
||||
// 定义内边距
|
||||
.u-p-#{$short}-#{$i} {
|
||||
padding-#{$long}: $i + rpx!important;
|
||||
}
|
||||
|
||||
// 完整版,结果如:u-margin-left-30
|
||||
// 定义外边距
|
||||
.u-margin-#{$long}-#{$i} {
|
||||
margin-#{$long}: $i + rpx!important;
|
||||
}
|
||||
|
||||
// 定义内边距
|
||||
.u-padding-#{$long}-#{$i} {
|
||||
padding-#{$long}: $i + rpx!important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 重置nvue的默认关于flex的样式
|
||||
.u-reset-nvue {
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/* start--文本行数限制--start */
|
||||
.u-line-1 {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.u-line-2 {
|
||||
-webkit-line-clamp: 2;
|
||||
}
|
||||
|
||||
.u-line-3 {
|
||||
-webkit-line-clamp: 3;
|
||||
}
|
||||
|
||||
.u-line-4 {
|
||||
-webkit-line-clamp: 4;
|
||||
}
|
||||
|
||||
.u-line-5 {
|
||||
-webkit-line-clamp: 5;
|
||||
}
|
||||
|
||||
.u-line-2, .u-line-3, .u-line-4, .u-line-5 {
|
||||
overflow: hidden;
|
||||
word-break: break-all;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box; // 弹性伸缩盒
|
||||
-webkit-box-orient: vertical; // 设置伸缩盒子元素排列方式
|
||||
}
|
||||
|
||||
/* end--文本行数限制--end */
|
||||
|
||||
|
||||
/* start--不同颜色文字--start */
|
||||
.color-333{
|
||||
color: #333;
|
||||
}
|
||||
.color-666{
|
||||
color: #666;
|
||||
}
|
||||
.color-999{
|
||||
color: #999;
|
||||
}
|
||||
.color-red{
|
||||
color: $my-red-color;
|
||||
}
|
||||
.color-main{
|
||||
color:$my-main-color
|
||||
}
|
||||
|
||||
/* end--不同颜色文字--end */
|
||||
|
||||
|
||||
.tranistion{
|
||||
transition: all .3s ease-in-out;
|
||||
}
|
||||
.tranistion-1{
|
||||
transition: all .1s ease-in-out;
|
||||
}
|
||||
.tranistion-2{
|
||||
transition: all .2s ease-in-out;
|
||||
}
|
||||
.font-bold{
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
|
||||
/* start--不同颜色背景--start */
|
||||
.my-bg-main{
|
||||
background-color:$my-main-color
|
||||
}
|
||||
|
||||
/* end--不同颜色背景--end */
|
||||
|
||||
.safe-page{
|
||||
padding-bottom: 60rpx!important;
|
||||
}
|
||||
::v-deep .uni-switch-input.uni-switch-input-checked{
|
||||
border-color: $my-main-color;
|
||||
background-color: $my-main-color;
|
||||
}
|
||||
.btn-circle{
|
||||
border-radius: 200px;
|
||||
}
|
||||
.min-page{
|
||||
/* #ifdef H5 */
|
||||
min-height: calc(100vh - 44px);
|
||||
/* #endif */
|
||||
/* #ifndef H5 */
|
||||
min-height: 100vh;
|
||||
/* #endif */
|
||||
}
|
||||
.w-full{
|
||||
width: 100%;
|
||||
}
|
||||
.gap-20{
|
||||
gap: 20rpx;
|
||||
}
|
||||
.color-000{
|
||||
color: #000;
|
||||
}
|
||||
.color-fff{
|
||||
color: #fff;
|
||||
}
|
||||
.bg-fff{
|
||||
background-color: #fff;
|
||||
}
|
||||
.bg-gray{
|
||||
background-color: #F9F9F9;
|
||||
}
|
||||
.overflow-hide{
|
||||
/* #ifdef H5 */
|
||||
height: calc(100vh - 44px);
|
||||
/* #endif */
|
||||
/* #ifndef H5 */
|
||||
height: 100vh;
|
||||
/* #endif */
|
||||
overflow: hidden;
|
||||
}
|
||||
.no-wrap{
|
||||
white-space: nowrap;
|
||||
}
|
||||
.border-r-12{
|
||||
border-radius: 12rpx;
|
||||
}
|
||||
.border-r-18{
|
||||
border-radius: 18rpx;
|
||||
}
|
||||
.border-top{
|
||||
border-top: 1px solid #E5E5E5;
|
||||
}
|
||||
.border-bottom{
|
||||
border-bottom: 1px solid #E5E5E5;
|
||||
}
|
||||
.scale7{
|
||||
transform: scale(0.7);
|
||||
}
|
||||
.page-gray {
|
||||
min-height: calc(100vh);
|
||||
/* #ifdef H5 */
|
||||
min-height: calc(100vh - var(--window-top));
|
||||
/* #endif */
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: #F9F9F9;
|
||||
}
|
||||
.box-shadow{
|
||||
box-shadow: 0 0 5px #eee;
|
||||
}
|
||||
.safe-bottom{
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
/* #ifdef H5 */
|
||||
padding-bottom: 28rpx;
|
||||
/* #endif */
|
||||
}
|
||||
.position-all{
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
.fixed-top{
|
||||
position: fixed;
|
||||
/* #ifdef H5 */
|
||||
top: 44px;
|
||||
/* #endif */
|
||||
/* #ifndef H5 */
|
||||
top: 0;
|
||||
/* #endif */
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
.lh30 {
|
||||
line-height: 30px;
|
||||
}
|
||||
.default-box-padding{
|
||||
padding: 32rpx 24rpx;
|
||||
}
|
||||
.icon-arrow-down-fill {
|
||||
width: 16rpx;
|
||||
height: 10rpx;
|
||||
}
|
||||
.zIndex-999{
|
||||
z-index: 999;
|
||||
}
|
||||
.icon-default-size{
|
||||
width: 28rpx;
|
||||
height: 28rpx;
|
||||
}
|
||||
::v-deep.uni-easyinput__placeholder-class{
|
||||
font-size: 28rpx!important;
|
||||
}
|
||||
.filter-gray{
|
||||
filter: grayscale(1);
|
||||
}
|
||||
// .u-font-20{
|
||||
// font-size: 10px;
|
||||
// }
|
||||
// .u-font-24{
|
||||
// font-size: 12px;
|
||||
// }
|
||||
// .u-font-28{
|
||||
// font-size: 14px;
|
||||
// }
|
||||
// .u-font-32{
|
||||
// font-size: 16px;
|
||||
// }
|
||||
.line-th{
|
||||
text-decoration: line-through;
|
||||
}
|
||||
//覆盖u-view-plus 颜色
|
||||
.u-primary-light {
|
||||
color: $my-main-color;
|
||||
}
|
||||
::v-deep .u-border{
|
||||
border-width: 1px!important;
|
||||
}
|
||||
|
||||
::v-deep .u-m-t-16 .u-textarea{
|
||||
border-width: 1px!important;
|
||||
}
|
||||
|
|
@ -0,0 +1,204 @@
|
|||
<template>
|
||||
<view class="qrcode">
|
||||
<up-qrcode :size="qrcodeData.size" :val="qrcodeData.val" @result="qrcodeResult"></up-qrcode>
|
||||
</view>
|
||||
<view class="poster-box" @click="hide">
|
||||
<view class="bg-fff container" @click.stop>
|
||||
<canvas canvas-id="myCanvas" class="myCanvas" id="myCanvas" style="width: 100%;flex: 1;"></canvas>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
<up-popup :show="posterData.result?true:false" mode="center" width="700rpx" closeOnClickOverlay @close="reset">
|
||||
<image :src="posterData.result" mode="widthFix"></image>
|
||||
</up-popup>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
getElRect
|
||||
} from '@/utils/util.js'
|
||||
import {
|
||||
ref,
|
||||
onMounted,
|
||||
getCurrentInstance,
|
||||
reactive,
|
||||
computed
|
||||
} from 'vue'
|
||||
let show = ref(false)
|
||||
function reset(){
|
||||
ctx.clearRect(0,0,posterData.width,posterData.height)
|
||||
show.value=false
|
||||
qrcodeData.val=''
|
||||
qrcodeData.result=''
|
||||
posterData.result=''
|
||||
}
|
||||
const qrcodeData = reactive({
|
||||
val: '',
|
||||
result: '',
|
||||
size: 80
|
||||
})
|
||||
|
||||
let posterData = reactive({
|
||||
width: 0,
|
||||
height: 0,
|
||||
result: ''
|
||||
})
|
||||
const ctx = uni.createCanvasContext('myCanvas')
|
||||
|
||||
function qrcodeResult(e) {
|
||||
console.log(e);
|
||||
qrcodeData.result = e
|
||||
console.log(posterData);
|
||||
const gap = 10
|
||||
show.value = true
|
||||
ctx.setFillStyle('#fff')
|
||||
ctx.fillRect(0, 0, posterData.width, posterData.height)
|
||||
uni.downloadFile({
|
||||
url: posterData.bigImg,
|
||||
success(res) {
|
||||
if (res.statusCode == 200) {
|
||||
uni.getImageInfo({
|
||||
src: res.tempFilePath,
|
||||
success(imageInfo) {
|
||||
console.log(imageInfo);
|
||||
const bili = imageInfo.width / imageInfo.height
|
||||
const width = posterData.width - gap * 2
|
||||
console.log(width);
|
||||
console.log(width / bili);
|
||||
ctx.drawImage(res.tempFilePath, gap, gap, width, width / bili, 0, 0)
|
||||
ctx.drawImage(e, posterData.width - qrcodeData.size - gap, posterData.height -
|
||||
gap - qrcodeData.size, qrcodeData.size, qrcodeData.size)
|
||||
ctx.setFillStyle('#000')
|
||||
ctx.setFontSize(14);
|
||||
ctx.fillText(posterData.title, gap, posterData.height - gap - 20)
|
||||
ctx.setFillStyle('#999')
|
||||
ctx.setFontSize(12);
|
||||
ctx.fillText(posterData.tips, gap, posterData.height - gap)
|
||||
ctx.draw()
|
||||
setTimeout(() => {
|
||||
uni.canvasToTempFilePath({
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: posterData.width,
|
||||
height: posterData.height,
|
||||
destWidth: posterData.width,
|
||||
destHeight: posterData.height,
|
||||
canvasId: 'myCanvas',
|
||||
quality: 1,
|
||||
success: function(res) {
|
||||
// 在H5平台下,tempFilePath 为 base64
|
||||
console.log(res.tempFilePath)
|
||||
posterData.result = res.tempFilePath
|
||||
}
|
||||
})
|
||||
}, 600)
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: '封面图下载失败'
|
||||
})
|
||||
}
|
||||
console.log(res);
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
show.value = true
|
||||
}
|
||||
|
||||
const props = defineProps({
|
||||
bigImg: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
function make(data) {
|
||||
uni.showLoading({
|
||||
title: '二维码生成中……'
|
||||
})
|
||||
Object.assign(posterData, data)
|
||||
qrcodeData.val = data.qrcode
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getElRect('myCanvas').then(res => {
|
||||
Object.assign(posterData, res)
|
||||
})
|
||||
})
|
||||
|
||||
function hide() {
|
||||
show.value = false
|
||||
}
|
||||
|
||||
|
||||
let canvasConfig = reactive({
|
||||
width: '',
|
||||
height: ''
|
||||
})
|
||||
|
||||
const canvasStyle = computed(() => {
|
||||
return {
|
||||
width: '',
|
||||
height: ''
|
||||
}
|
||||
})
|
||||
|
||||
defineExpose({
|
||||
make
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.qrcode {
|
||||
position: fixed;
|
||||
top: -9999px;
|
||||
left: -9999px;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.u-popup {
|
||||
position: fixed !important;
|
||||
}
|
||||
|
||||
::v-deep .u-popup {
|
||||
position: fixed !important;
|
||||
}
|
||||
|
||||
.poster-box {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
z-index: 9999;
|
||||
background-color: rgba(0, 0, 0, .5);
|
||||
transform: translateY(-100%);
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
transition: all .3s ease-in-out;
|
||||
padding: 30rpx;
|
||||
|
||||
.container {
|
||||
width: 100%;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
&.show {
|
||||
transform: translateY(0px);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,433 @@
|
|||
<template>
|
||||
<view class="item" @appear="appear" @disappear="disappear" @click.stop>
|
||||
|
||||
<video class="u-flex-1 video" :show-fullscreen-btn="false" @controlstoggle="controlstoggles" v-if="showVideo"
|
||||
@waiting="waiting()" object-fit="cover"
|
||||
@pause="onpause"
|
||||
@play="videoPlay('myVideo'+item.courseDetailsId,item.courseDetailsId)" :play-strategy="2"
|
||||
:show-loading="true" codec="software" :muted="false" :show-center-play-btn="true" :loop="false"
|
||||
:enable-progress-gesture="false" :poster="item.titleImg" :ref="'myVideo'+item.courseDetailsId"
|
||||
:autoplay="autoplay" @ended="ended" :id="'myVideo'+item.courseDetailsId" :src="item.videoUrl"></video>
|
||||
|
||||
<image class="poster" v-else @click="!item.videoUrl?popupShow('pay'):''" :src="item.titleImg" mode="aspectFill">
|
||||
</image>
|
||||
|
||||
<view class="info" v-if="!isCommand" :style="infoStyle">
|
||||
<text class="color-fff" v-if="item.courseDetailsName">{{item.courseDetailsName}}</text>
|
||||
<view v-if="item.content" v-html="item.content"></view>
|
||||
<view class="u-m-t-20 color-fff" @click="popupShow('show')">
|
||||
<text class="color-fff">
|
||||
{{item.courseDetailsName}}(共{{total}}集)选集 >
|
||||
</text>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
<view class="info" v-if="isCommand" :style="infoStyle">
|
||||
<text class="color-fff" v-if="item.courseDetailsName">{{item.courseDetailsName}}</text>
|
||||
<view v-if="item.content" v-html="item.content"></view>
|
||||
<view class="u-m-t-20 color-fff" @click="toDetail">
|
||||
<text class="color-fff">
|
||||
查看更多续集 >
|
||||
</text>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
<view class="right" :style="rightStyle">
|
||||
<view class="love u-flex u-flex-xy-center u-flex-col u-m-b-40 u-text-center" @click="dianzanClick">
|
||||
<up-icon name="heart-fill" v-if="item.isGood==1" color="red" size="30"></up-icon>
|
||||
<up-icon name="heart-fill" v-else color="#ffffff" size="30"></up-icon>
|
||||
<text class="text color-fff u-font-24">{{item.goodNum}}</text>
|
||||
</view>
|
||||
<view class="share u-m-b-40 u-flex u-flex-xy-center u-flex-col u-text-center" @click="share">
|
||||
<image class="icon" src="@/static/images/share.png" mode=""></image>
|
||||
<text class="text color-fff u-font-24">分享</text>
|
||||
</view>
|
||||
<view class="zhuiju u-m-b-40 u-flex u-flex-xy-center u-flex-col u-text-center" @click="zhuijuClick">
|
||||
<image class="icon" v-if="isCollect" src="@/static/images/shuqian.png" mode=""></image>
|
||||
<image class="icon" v-else src="@/static/images/shuqian_s.png" mode=""></image>
|
||||
<text class="text color-fff u-font-24">{{isCollect?'已追':'追剧'}}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
computed,
|
||||
nextTick,
|
||||
onMounted,
|
||||
ref,
|
||||
watch
|
||||
} from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
item: {
|
||||
type: Object,
|
||||
defaulr: () => {
|
||||
return {
|
||||
videoUrl: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
rightStyle:{
|
||||
type:Object,
|
||||
default:()=>{
|
||||
return {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
infoStyle:{
|
||||
type:Object,
|
||||
default:()=>{
|
||||
return {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
isCommand: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
instance: {
|
||||
type: Object,
|
||||
defaulr: () => {
|
||||
return {
|
||||
proxy: {}
|
||||
}
|
||||
}
|
||||
},
|
||||
current: {
|
||||
//h5判断是否是当前项目
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
index: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
nowIndex: {
|
||||
//app判断是否是当前项目
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
total: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
isCollect: {
|
||||
type: [Number, Boolean],
|
||||
default: 0
|
||||
},
|
||||
playSpeeds: {
|
||||
type: Number,
|
||||
default: 1
|
||||
},
|
||||
showControls:{
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
})
|
||||
let autoplay = ref(props.item.videoUrl ? true : false)
|
||||
|
||||
const emits = defineEmits(['controlstoggles', 'disappear', 'appear', 'waiting', 'videoPlay', 'ended', 'dianzanClick',
|
||||
'share', 'zhuijuClick', 'popupShow', 'itemMounted', 'toDetail'
|
||||
])
|
||||
|
||||
function controlstoggles(e) {
|
||||
console.log(e);
|
||||
emits('controlstoggles', e)
|
||||
}
|
||||
|
||||
function toDetail() {
|
||||
if (video) {
|
||||
video.pause()
|
||||
}
|
||||
emits('toDetail')
|
||||
}
|
||||
|
||||
function waiting() {
|
||||
|
||||
}
|
||||
|
||||
function videoPlay() {
|
||||
// #ifdef H5
|
||||
emits('controlstoggles', {
|
||||
detail:{show:true}
|
||||
})
|
||||
// #endif
|
||||
|
||||
}
|
||||
|
||||
function onpause(){
|
||||
// #ifdef H5
|
||||
emits('controlstoggles', {
|
||||
detail:{show:false}
|
||||
})
|
||||
// #endif
|
||||
}
|
||||
|
||||
function ended() {
|
||||
|
||||
}
|
||||
|
||||
function dianzanClick() {
|
||||
emits('dianzanClick')
|
||||
}
|
||||
|
||||
function share() {
|
||||
emits('share')
|
||||
}
|
||||
|
||||
function zhuijuClick() {
|
||||
emits('zhuijuClick')
|
||||
}
|
||||
|
||||
function popupShow(key) {
|
||||
emits('popupShow', key)
|
||||
}
|
||||
|
||||
let first = true
|
||||
|
||||
function appear() {
|
||||
if (video) {
|
||||
video.playbackRate(props.playSpeeds)
|
||||
video.play()
|
||||
}
|
||||
emits('appear', first)
|
||||
if (first) {
|
||||
first = false
|
||||
}
|
||||
}
|
||||
|
||||
let video = null
|
||||
|
||||
function disappear() {
|
||||
if (video) {
|
||||
video.pause()
|
||||
}
|
||||
emits('disappear')
|
||||
}
|
||||
const showVideo = computed(() => {
|
||||
// #ifdef H5
|
||||
return props.current === props.index && props.item.videoUrl
|
||||
// #endif
|
||||
// #ifdef APP
|
||||
return props.nowIndex === props.index && props.item.videoUrl
|
||||
// #endif
|
||||
})
|
||||
onMounted(() => {
|
||||
init()
|
||||
emits('itemMounted', props.index)
|
||||
})
|
||||
|
||||
function init() {
|
||||
try {
|
||||
if (props.item.videoUrl && showVideo.value) {
|
||||
video = uni.createVideoContext('myVideo' + props.item.courseDetailsId)
|
||||
video.playbackRate(props.playSpeeds)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('------')
|
||||
//TODO handle the exception
|
||||
}
|
||||
}
|
||||
watch(() => props.playSpeeds, (newval) => {
|
||||
console.log('speed' + newval);
|
||||
if (video) {
|
||||
video.playbackRate(newval)
|
||||
}
|
||||
})
|
||||
watch(() => showVideo.value, (newval) => {
|
||||
if (newval) {
|
||||
init()
|
||||
} else {
|
||||
video = null
|
||||
}
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.item {
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.box {
|
||||
/* #ifdef H5 */
|
||||
flex: 1;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.u-flex-1 {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.u-popup {
|
||||
position: fixed !important;
|
||||
}
|
||||
|
||||
::v-deep .u-popup {
|
||||
position: fixed !important;
|
||||
}
|
||||
|
||||
.video {
|
||||
width: 750rpx;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.poster {
|
||||
/* #ifdef H5 */
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 90%;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
/* #endif */
|
||||
/* #ifdef APP */
|
||||
width: 750rpx;
|
||||
flex: 1;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.u-text-center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.u-flex-row {
|
||||
flex-direction: row !important;
|
||||
}
|
||||
|
||||
.info {
|
||||
/* #ifdef H5 */
|
||||
width: 80%;
|
||||
/* #endif */
|
||||
height: auto;
|
||||
position: absolute !important;
|
||||
bottom: 50px;
|
||||
left: 10px;
|
||||
color: #ffffff;
|
||||
font-size: 15px;
|
||||
z-index: 9999;
|
||||
transition: all .3s ease-in-out;
|
||||
}
|
||||
|
||||
.u-flex-y-center {
|
||||
align-items: center !important;
|
||||
}
|
||||
|
||||
.swipers-items {
|
||||
width: 750rpx;
|
||||
flex: 1;
|
||||
position: relative;
|
||||
background-color: #000;
|
||||
}
|
||||
|
||||
.right {
|
||||
transition: all .3s ease-in-out;
|
||||
position: absolute !important;
|
||||
right: 20rpx;
|
||||
/* #ifdef H5 */
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
/* #endif */
|
||||
/* #ifdef APP */
|
||||
top: 500px;
|
||||
/* #endif */
|
||||
z-index: 999;
|
||||
color: #fff;
|
||||
font-size: 24rpx;
|
||||
|
||||
.icon {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
}
|
||||
|
||||
.share {
|
||||
.text {
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
.zhuiju {}
|
||||
}
|
||||
|
||||
.poster-popup {
|
||||
position: fixed !important;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
background-color: rgba(0, 0, 0, 0.6);
|
||||
z-index: 9999;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.ji-list {
|
||||
.ji-item {
|
||||
width: 210rpx;
|
||||
margin-bottom: 20rpx;
|
||||
margin-right: 30rpx;
|
||||
height: 88rpx;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
border-radius: 12rpx;
|
||||
background-color: #F5F7FF;
|
||||
position: relative;
|
||||
|
||||
&.active {
|
||||
background-color: $my-main-color;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.lock {
|
||||
position: absolute;
|
||||
border-radius: 0px 6px 0px 6px;
|
||||
background-color: #ccc;
|
||||
padding: 2rpx 4rpx;
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.playing {
|
||||
position: absolute;
|
||||
width: 32rpx;
|
||||
height: 24rpx;
|
||||
bottom: 5px;
|
||||
right: 7px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ji-item:nth-of-type(3n) {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.hot {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
}
|
||||
|
||||
.pay-list {
|
||||
.pay-list-item {
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
background-color: #F2F2F2;
|
||||
padding: 24rpx;
|
||||
border-radius: 20rpx;
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.zhifubao {
|
||||
width: 56rpx;
|
||||
height: 56rpx;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,60 +1,181 @@
|
|||
<template>
|
||||
<view class="u-flex-1">
|
||||
<!-- #ifdef H5 -->
|
||||
<swiper @change="swiperChange" :current="current" :circular="true" vertical class="u-flex-1"
|
||||
<!-- #ifdef H5 -->
|
||||
<view class=" w-full box" style="width: 100vw;">
|
||||
<swiper @longpress="popupShow('speed')" :style="{height:wHeight+'px'}" v-if="videoList.length"
|
||||
@change="swiperChange" :current="current" :circular="true" vertical class="u-flex-1"
|
||||
@transition="transition" :indicator-dots="false" :autoplay="false" :interval="0" :duration="200">
|
||||
<swiper-item v-for="(item,index) in videoList" :key="index">
|
||||
|
||||
<video class="u-flex-1 video" :show-fullscreen-btn="false" @controlstoggle="controlstoggles"
|
||||
v-if="current === index && item.videoUrl" @waiting="waiting()" object-fit="cover"
|
||||
@play="videoPlay('myVideo'+item.courseDetailsId,item.courseDetailsId)" :play-strategy="2"
|
||||
:show-loading="true" codec="software" :muted="false" :show-center-play-btn="true" :loop="false"
|
||||
:enable-progress-gesture="false" :poster="item.titleImg" :ref="'myVideo'+item.courseDetailsId"
|
||||
@ended="ended" :id="'myVideo'+item.courseDetailsId" :src="item.videoUrl"
|
||||
:autoplay="item.autoPlay"></video>
|
||||
|
||||
<image class="poster" v-else @click="openShowPay(current,index,item.videoUrl)" :src="item.titleImg"
|
||||
mode="aspectFill"></image>
|
||||
|
||||
<view class="info">
|
||||
<text v-if="item.courseDetailsName">{{item.courseDetailsName}}</text>
|
||||
<view v-if="item.content" v-html="item.content"></view>
|
||||
<text class="u-m-t-20">
|
||||
{{item.courseDetailsName}}(共{{list.length}}集)选集 >
|
||||
</text>
|
||||
</view>
|
||||
<view class="right">
|
||||
<view class="love u-m-b-40 u-flex-y-center u-flex-x-center u-text-center">
|
||||
<up-icon name="heart-fill" v-if="item.isGood==1" color="red" size="30"></up-icon>
|
||||
<up-icon name="heart-fill" v-else color="#ffffff" size="30"></up-icon>
|
||||
<text class="text">{{item.goodNum}}</text>
|
||||
</view>
|
||||
<view class="share u-m-b-40 u-flex-y-center u-flex-x-center u-text-center" @click="share(item)">
|
||||
<image class="icon" src="@/static/images/share.png" mode=""></image>
|
||||
<text class="text">分享</text>
|
||||
</view>
|
||||
<view class="zhuiju u-m-b-40 u-flex-y-center u-flex-x-center u-text-center" @click="zhuijuClick">
|
||||
<image class="icon" v-if="isCollect" src="@/static/images/shuqian.png" mode=""></image>
|
||||
<image class="icon" v-else src="@/static/images/shuqian_s.png" mode=""></image>
|
||||
<text class="text">{{isCollect?'已追':'追剧'}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<list-item-vue :total="list.length" :item="item" :isCommand="isCommand"
|
||||
:rightStyle="rightStyle" :infoStyle="infoStyle"
|
||||
:showControls="control.showControls" :current="current" :isCollect="isCollect"
|
||||
@toDetail="toDetail(item,index)" @controlstoggles="controlstoggles" :playSpeeds="playSpeeds"
|
||||
:index="index" :nowIndex="nowIndex" @dianzanClick="dianzanClick(item,index)" @share="share(item)"
|
||||
@zhuijuClick="zhuijuClick(item)" @popupShow="popupShow"></list-item-vue>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
<!-- #endif -->
|
||||
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
|
||||
<!-- #ifdef APP -->
|
||||
<list :bounce="false" :loadmoreoffset="wHeight*3" :show-scrollbar="false" ref="listBox" :pagingEnabled="true"
|
||||
@loadmore="loadmore" :scrollable="true">
|
||||
<cell v-for="(item,index) in list" :key="item.courseDetailsId" :ref="setRefList(index)">
|
||||
<view class="swipers-items" :style="boxStyle" @longpress="popupShow('speed')">
|
||||
<list-item-vue :total="list.length" :item="item" :current="current" :isCollect="isCollect"
|
||||
:rightStyle="rightStyle" :infoStyle="infoStyle"
|
||||
:isCommand="isCommand" :showControls="control.showControls" @toDetail="toDetail(item,index)"
|
||||
@itemMounted="itemMounted" @controlstoggles="controlstoggles" :index="index" :instance="instance"
|
||||
:nowIndex="nowIndex" @appear="appear($event,item,index)" :playSpeeds="playSpeeds"
|
||||
@disappear="disappear(item,index)" @dianzanClick="dianzanClick(item,index)" @share="share(item)"
|
||||
@zhuijuClick="zhuijuClick(item)" @popupShow="popupShow"></list-item-vue>
|
||||
</view>
|
||||
</cell>
|
||||
</list>
|
||||
|
||||
<!-- #endif -->
|
||||
|
||||
<!-- 返回按钮 -->
|
||||
<view class="back-icon" v-if="!isTabbar&&control.showBack">
|
||||
<u-icon name="arrow-left" color="#fff" :size="28" @click="back"></u-icon>
|
||||
</view>
|
||||
|
||||
<!-- 选集 -->
|
||||
<up-popup :show="popup.show" :round="10" @close="popupClose('show')" :customStyle="customStyle">
|
||||
<view class="u-p-30">
|
||||
<view class="u-flex u-flex-row u-row-between">
|
||||
<view class="u-flex u-flex-row" style="align-items: baseline;">
|
||||
<text class="color-333 u-font-32 ">{{info.title}}</text>
|
||||
<text class="u-font-28 color-666 u-m-l-20">共{{list.length}}集</text>
|
||||
</view>
|
||||
<up-icon name="close" :size="16" color="#333" bold @click="popupClose('show')"></up-icon>
|
||||
</view>
|
||||
<scroll-view scroll-y="true" class="u-m-t-30" style="height: 400px;box-sizing: border-box;"
|
||||
:show-scrollbar="false">
|
||||
<view class="ji-list u-flex u-flex-row u-flex-wrap">
|
||||
<view class="ji-item u-flex-xy-center u-text-center" @click="jiClick(item,index)"
|
||||
:class="{active:nowIndex==index,'mr-0':(index+1)%3==0}" v-for="(item,index) in list"
|
||||
:key="index">
|
||||
<text class="u-font-28" :class="{'color-fff':nowIndex==index}">第{{index+1}}集</text>
|
||||
<view class="lock u-flex-xy-center" v-if="!item.videoUrl">
|
||||
<up-icon name="lock" :size="14" color="#fff"></up-icon>
|
||||
</view>
|
||||
<image v-if="nowIndex==index" class="playing" src="@/static/images/playIng.png" mode="">
|
||||
</image>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</scroll-view>
|
||||
</view>
|
||||
</up-popup>
|
||||
<!-- 支付 -->
|
||||
<up-popup :show="popup.pay" :round="10" @close="popupClose('pay')" :customStyle="customStyle">
|
||||
<view class="u-p-30">
|
||||
<view class="u-flex u-flex-row u-row-between">
|
||||
<view class="u-flex u-flex-row" style="align-items: baseline;">
|
||||
<text class="color-333 u-font-32 ">当前视频 没有播放权限</text>
|
||||
</view>
|
||||
<up-icon name="close" :size="16" color="#333" bold @click="popupClose('pay')"></up-icon>
|
||||
</view>
|
||||
<view class="u-m-t-30">
|
||||
<text class=" color-999 u-font-24">每日前10次付款均可获取抽奖机会,抽奖保底抽中付款金额等额红包,红包可直接提现。当前为第1次付款</text>
|
||||
</view>
|
||||
<view class="colo-333 pay-list font-bold u-font-28 u-m-t-20">
|
||||
<view class="pay-list-item" v-if="info&&info.price" @click="payBtnClick">
|
||||
<image class="hot" src="@/static/images/hot.png" mode=""></image>
|
||||
<text class="u-font-28 font-bold">{{info.price}}元解锁全剧</text>
|
||||
</view>
|
||||
<view class="pay-list-item" @click="payBtnClick">
|
||||
<image class="hot" src="@/static/images/hot.png" mode=""></image>
|
||||
<text class="u-font-28 font-bold">{{nowDanjiPrice*jinbiBili}}金币解锁单集视频</text>
|
||||
</view>
|
||||
<view class="pay-list-item" @click="payBtnClick">
|
||||
<!-- <image class="hot" src="@/static/images/hot.png" mode=""></image> -->
|
||||
<text class="u-font-28 font-bold">{{nowDanjiPrice}}元解锁单集视频</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</up-popup>
|
||||
<!-- 支付确认 -->
|
||||
<up-popup :show="popup.payTips" :round="10" @close="popupClose('payTips')" :customStyle="customStyle">
|
||||
<view class="u-p-30">
|
||||
<view class="u-flex u-flex-row u-row-between">
|
||||
<view class="u-flex u-flex-row" style="align-items: baseline;">
|
||||
<text class="color-333 u-font-32 ">购买后继续观看</text>
|
||||
</view>
|
||||
<up-icon name="close" :size="16" color="#333" bold @click="popupClose('payTips')"></up-icon>
|
||||
</view>
|
||||
<view class="u-flex u-m-t-24 u-flex-row u-row-between u-font-28">
|
||||
<view class="u-flex u-flex-row u-flex-y-center">
|
||||
<image src="@/static/images/zhifubao.png" class="zhifubao" mode=""></image>
|
||||
<text class="u-m-l-20 u-flex-xy-center u-font-28">支付宝</text>
|
||||
</view>
|
||||
<view>
|
||||
<up-radio-group>
|
||||
<up-radio :icon-size="20" :size="26" :activeColor="color.main"></up-radio>
|
||||
</up-radio-group>
|
||||
</view>
|
||||
</view>
|
||||
<view class="u-m-t-10">
|
||||
<text class="font-bold u-font-26 color-333">温馨提示</text>
|
||||
<text class="u-m-t-10 u-font-24 color-999">一经购买不予退款,未满18岁需在监护人的指导、同意下进行付费操作</text>
|
||||
</view>
|
||||
<view class="u-flex u-flex-row u-m-t-30 u-flex-y-center u-font-28">
|
||||
<view class="u-flex-y-center">
|
||||
<up-checkbox usedAlone shape="circle" v-model="isAgree" :activeColor="color.main"></up-checkbox>
|
||||
</view>
|
||||
<view class="u-flex u-flex-row u-flex-y-center">
|
||||
<text class="u-font-28 color-333">我已经阅读并同意</text>
|
||||
<text class="color-main u-font-28">《付费须知说明》</text>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
<view class="u-m-t-30 my-bg-main payConfirm">
|
||||
<text class="u-font-28 color-fff">确认支付</text>
|
||||
</view>
|
||||
</view>
|
||||
</up-popup>
|
||||
|
||||
<!-- 倍速 -->
|
||||
<up-popup :show="popup.speed" :round="0" @close="popupClose('speed')" :customStyle="customStyle">
|
||||
<view class="u-p-20 u-flex u-flex-row u-row-between u-flex-y-center">
|
||||
<text class="font-bold color-333 u-font-28">倍速:</text>
|
||||
|
||||
<view class="u-flex u-flex-row speed-list">
|
||||
<text class="speed-list-item u-font-28" @click="changeSpeed(index)"
|
||||
:class="{active:index==speeds.active}" v-for="(item,index) in speeds.list">{{item.num}}x</text>
|
||||
</view>
|
||||
</view>
|
||||
</up-popup>
|
||||
|
||||
<my-poster ref="refPoster"></my-poster>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {returnShareUrl} from '@/commons/config.js'
|
||||
// #ifdef APP
|
||||
const domModule = uni.requireNativePlugin('dom')
|
||||
// #endif
|
||||
import listItemVue from './list-item.vue';
|
||||
import {
|
||||
returnShareUrl
|
||||
} from '@/commons/config.js'
|
||||
import color from '@/commons/color.js'
|
||||
import {
|
||||
debounce
|
||||
} from 'lodash';
|
||||
import * as Api from '@/api/video/index.js'
|
||||
import infoBox from '@/utils/infoBox.js'
|
||||
import {
|
||||
computed,
|
||||
reactive,
|
||||
ref,
|
||||
watch
|
||||
watch,
|
||||
nextTick,
|
||||
onMounted,
|
||||
getCurrentInstance
|
||||
} from 'vue';
|
||||
|
||||
const refPoster = ref(null)
|
||||
|
||||
const props = defineProps({
|
||||
list: {
|
||||
type: Array,
|
||||
|
|
@ -62,42 +183,316 @@
|
|||
[]
|
||||
}
|
||||
},
|
||||
isCollect: {
|
||||
isCommand: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
isTabbar: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
info: {
|
||||
tpye: Object,
|
||||
default: () => {
|
||||
return {
|
||||
collect: 0,
|
||||
current: {},
|
||||
list: [],
|
||||
price: 0,
|
||||
title: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
const control = reactive({
|
||||
showBack: true,
|
||||
showControls: true
|
||||
})
|
||||
// #ifdef APP
|
||||
control.showControls=false
|
||||
// #endif
|
||||
|
||||
function posterError(){
|
||||
const customStyle = computed(() => {
|
||||
// #ifdef H5
|
||||
return {
|
||||
bottom: props.isTabbar ? '50px' : '0'
|
||||
}
|
||||
// #endif
|
||||
// #ifndef H5
|
||||
return {}
|
||||
// #endif
|
||||
})
|
||||
|
||||
function controlstoggles(e) {
|
||||
control.showControls = e.detail.show
|
||||
console.log(control.showControls );
|
||||
control.showBack = control.showControls
|
||||
console.log(control);
|
||||
}
|
||||
|
||||
function posterSuccess(){
|
||||
const speeds = reactive({
|
||||
list: [{
|
||||
name: '0.5x',
|
||||
num: 0.5
|
||||
}, {
|
||||
name: '1x',
|
||||
num: 1
|
||||
}, {
|
||||
name: '1.25x',
|
||||
num: 1.25
|
||||
}, {
|
||||
name: '1.5x',
|
||||
num: 1.5
|
||||
}],
|
||||
active: 1
|
||||
})
|
||||
|
||||
const $mountedComponents = {}
|
||||
|
||||
function itemMounted(index) {
|
||||
// $mountedComponents[index]=true
|
||||
}
|
||||
|
||||
const posterData=reactive({
|
||||
posterShow:false
|
||||
function back() {
|
||||
const arr = getCurrentPages()
|
||||
if (arr.length < 2) {
|
||||
uni.switchTab({
|
||||
url: '/pages/index/index'
|
||||
})
|
||||
return
|
||||
}
|
||||
uni.navigateBack()
|
||||
}
|
||||
|
||||
function changeSpeed(index) {
|
||||
speeds.active = index
|
||||
uni.showToast({
|
||||
title: '已切换' + speeds.list[index].num + '倍播放',
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
})
|
||||
}
|
||||
const playSpeeds = computed(() => {
|
||||
return speeds.list[speeds.active].num
|
||||
})
|
||||
|
||||
const instance = getCurrentInstance()
|
||||
let isAgree = ref(false);
|
||||
const cutomStyle = {
|
||||
background: 'rgb(255, 117, 129)',
|
||||
height: '100rpx',
|
||||
'border-radius': '100px'
|
||||
}
|
||||
const popup = reactive({
|
||||
show: false,
|
||||
pay: false,
|
||||
payTips: false,
|
||||
speed: false
|
||||
})
|
||||
|
||||
|
||||
let videoList = ref(props.list.slice(0, 3))
|
||||
watch(() => props.list.length, (newval) => {
|
||||
init()
|
||||
function openBs() {
|
||||
|
||||
}
|
||||
|
||||
let cacheIndex = null
|
||||
|
||||
function appear(isFirst, item, index) {
|
||||
if (isFirst) {
|
||||
$mountedComponents[index] = true
|
||||
}
|
||||
if (!initing) {
|
||||
cacheIndex = index
|
||||
}
|
||||
}
|
||||
|
||||
function disappear(item, index) {
|
||||
|
||||
if (index == nowIndex.value && cacheIndex != null && !initing) {
|
||||
console.log('disappear' + index);
|
||||
console.log('disappear nowIndex' + nowIndex.value);
|
||||
console.log('cacheIndex' + cacheIndex);
|
||||
nowIndex.value = cacheIndex
|
||||
cacheIndex = null
|
||||
console.log('disappear,nowIndex=' + nowIndex.value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//确认支付
|
||||
function payConfirm() {
|
||||
if (!isAgree.value) {
|
||||
return infoBox.showToast('请阅读并同意 《付费须知说明》')
|
||||
}
|
||||
}
|
||||
|
||||
function payBtnClick() {
|
||||
popupClose()
|
||||
popupShow('payTips')
|
||||
}
|
||||
|
||||
|
||||
|
||||
function jiClick(item, index) {
|
||||
let newCurrent = (current.value + 1) % 3;
|
||||
videoList.value[newCurrent] = item;
|
||||
current.value = newCurrent;
|
||||
popupClose('show')
|
||||
// #ifdef APP
|
||||
goListPosition(index)
|
||||
// #endif
|
||||
}
|
||||
|
||||
let refList = ref([])
|
||||
|
||||
function setRefList(index) {
|
||||
refList.value[index] = null;
|
||||
return (el) => {
|
||||
if (el) {
|
||||
refList.value[index] = el;
|
||||
}
|
||||
};
|
||||
}
|
||||
//滚动到指定位置
|
||||
function goListPosition(index) {
|
||||
console.log('goListPosition:' + index)
|
||||
const el = refList.value[index]
|
||||
if ($mountedComponents[props.list.length - 1]) {
|
||||
domModule.scrollToElement(el, {
|
||||
animated: false
|
||||
})
|
||||
initing = false;
|
||||
const item = props.list[index]
|
||||
setVideoList(item)
|
||||
insertHistory()
|
||||
} else {
|
||||
setTimeout(() => {
|
||||
goListPosition(index)
|
||||
}, 30)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function popupClose(key) {
|
||||
if (key) {
|
||||
popup[key] = false
|
||||
return
|
||||
}
|
||||
for (let i in popup) {
|
||||
popup[i] = false
|
||||
}
|
||||
}
|
||||
|
||||
function popupShow(key = 'show') {
|
||||
popup[key] = true
|
||||
}
|
||||
|
||||
|
||||
let jinbiBili = ref(0)
|
||||
let wHeight = ref(0)
|
||||
async function configInit() {
|
||||
const res = await Api.getJinbiBili()
|
||||
jinbiBili.value = res.value
|
||||
|
||||
const sysInfo = uni.getSystemInfoSync()
|
||||
wHeight.value = sysInfo.windowHeight
|
||||
// wHeight.value = sysInfo.screenHeight
|
||||
}
|
||||
|
||||
let isCollect = ref(props.info.collect)
|
||||
watch(() => props.collect, (newval) => {
|
||||
isCollect.value = newval
|
||||
})
|
||||
|
||||
function toDetail(item, index) {
|
||||
uni.navigateTo({
|
||||
url: '/pages/video/detail?courseId=' + item.courseId
|
||||
})
|
||||
}
|
||||
|
||||
function posterError() {
|
||||
|
||||
}
|
||||
|
||||
function posterSuccess() {
|
||||
|
||||
}
|
||||
|
||||
const posterData = reactive({
|
||||
show: false,
|
||||
// 用户姓名
|
||||
name: '小明',
|
||||
// 用户头像
|
||||
logo: '/static/images/share.png',
|
||||
// 商品名称
|
||||
title: '精美时尚苹果手机一部',
|
||||
// 商品价格
|
||||
money: '5200.90',
|
||||
// 商品图片(小程序需要换成自己服务器白名单设置的地址)
|
||||
img: '',
|
||||
// 商品链接
|
||||
url: 'https://www.apple.com.cn/iphone/'
|
||||
|
||||
})
|
||||
let nowIndex = ref(0)
|
||||
let current = ref(0)
|
||||
let videoList = ref([])
|
||||
|
||||
|
||||
function init() {
|
||||
if (current.value === 0 && nowIndex.value == 0) {
|
||||
videoList.value = [props.list[0], props.list[1], props.list[props.list.length - 1]]
|
||||
} else {
|
||||
videoList.value = props.list.slice(0, 3)
|
||||
if (JSON.stringify(props.current) !== '{}') {
|
||||
// #ifdef H5
|
||||
setVideoList(props.info.current)
|
||||
// #endif
|
||||
// #ifdef APP
|
||||
nextTick(() => {
|
||||
const index = props.list.findIndex(v => v.courseDetailsId == props.info.current.courseDetailsId)
|
||||
goListPosition(index)
|
||||
})
|
||||
// #endif
|
||||
}
|
||||
}
|
||||
const emits = defineEmits(['zhuijuClick'])
|
||||
|
||||
function zhuijuClick() {
|
||||
emits(['zhuijuClick', 'swiperChange','share'])
|
||||
|
||||
const emits = defineEmits(['zhuijuClick', 'swiperChange', 'share', 'update'])
|
||||
|
||||
|
||||
|
||||
function zhuijuClick(item) {
|
||||
isCollect.value = !isCollect.value
|
||||
zhuiju({
|
||||
courseId: item.courseId,
|
||||
type: isCollect.value ? 1 : 0
|
||||
})
|
||||
emits('zhuijuClick')
|
||||
}
|
||||
const zhuiju = debounce((data) => {
|
||||
Api.zhuiju(data)
|
||||
}, 500)
|
||||
|
||||
let dianZanTimer = null
|
||||
|
||||
function dianzanClick(item, index) {
|
||||
item.isGood = !item.isGood
|
||||
const newval = item.goodNum + (item.isGood ? 1 : -1)
|
||||
item.goodNum = newval < 0 ? 0 : newval
|
||||
emits('update', {
|
||||
index,
|
||||
item
|
||||
})
|
||||
dianzan(item, index)
|
||||
}
|
||||
|
||||
const dianzan = debounce((item, index) => {
|
||||
Api.dianzan({
|
||||
courseId: item.courseId,
|
||||
courseDetailsId: item.courseDetailsId,
|
||||
type: item.isGood ? 1 : 0
|
||||
})
|
||||
}, 500)
|
||||
|
||||
|
||||
|
||||
let showControls = ref(false)
|
||||
|
||||
|
|
@ -105,11 +500,7 @@
|
|||
showControls.value = true
|
||||
}
|
||||
|
||||
let current = ref(0)
|
||||
|
||||
function controlstoggles() {
|
||||
|
||||
}
|
||||
|
||||
function videoPlay(videoId, courseDetailsId) {
|
||||
|
||||
|
|
@ -120,22 +511,62 @@
|
|||
}
|
||||
|
||||
function share(item) {
|
||||
emits('share',item)
|
||||
const urls = returnShareUrl() + '/me/detail/detail?id=' + item.courseId + '&courseDetailsId=' + item
|
||||
.courseDetailsId + '&invitation=' + uni.getStorageSync('invitationCode') + '&qdCode=' + this.qdCode;
|
||||
console.log(urls);
|
||||
// #ifdef H5
|
||||
refPoster.value.make({
|
||||
qrcode: urls,
|
||||
title: props.info.title,
|
||||
bigImg: item.titleImg,
|
||||
tips: '长按或扫描识别二维码观看'
|
||||
})
|
||||
// #endif
|
||||
|
||||
// #ifndef H5
|
||||
uni.setClipboardData({
|
||||
data: urls,
|
||||
success() {
|
||||
uni.showToast({
|
||||
title: '邀请链接已复制到剪贴板',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
})
|
||||
// #endif
|
||||
|
||||
}
|
||||
let nowIndex = ref(0)
|
||||
|
||||
function posterHide() {
|
||||
posterData.show = false
|
||||
}
|
||||
|
||||
|
||||
|
||||
const insertHistory = debounce(() => {
|
||||
const item = videoList.value[current.value]
|
||||
Api.insertHistory({
|
||||
courseId: item.courseId,
|
||||
courseDetailsId: item.courseDetailsId
|
||||
})
|
||||
}, 1000)
|
||||
|
||||
function swiperChange(e) {
|
||||
console.log(e);
|
||||
const direction = e.detail.current > current.value ? 'down' : 'up'
|
||||
console.log('e.detail.current');
|
||||
console.log(e.detail.current);
|
||||
current.value = e.detail.current
|
||||
const item = videoList.value[e.detail.current]
|
||||
insertHistory()
|
||||
setVideoList(item)
|
||||
}
|
||||
|
||||
|
||||
function setVideoList(item) {
|
||||
const listLen = props.list.length
|
||||
const lastIndex = listLen - 1
|
||||
const index = props.list.findIndex(v => v.courseDetailsId == item.courseDetailsId)
|
||||
nowIndex.value = index
|
||||
console.log('setVideoList nowIndex' + index);
|
||||
let position = ''
|
||||
if (index === 0) {
|
||||
position = 'start'
|
||||
|
|
@ -143,7 +574,6 @@
|
|||
if (index === props.list.length - 1) {
|
||||
position = 'end'
|
||||
}
|
||||
console.log(position);
|
||||
if (current.value == 0) {
|
||||
if (position === 'start') {
|
||||
videoList.value = [item, props.list[index + 1], props.list[lastIndex]]
|
||||
|
|
@ -172,6 +602,9 @@
|
|||
}
|
||||
}
|
||||
console.log(videoList.value);
|
||||
if (!item.videoUrl) {
|
||||
popupShow('pay')
|
||||
}
|
||||
}
|
||||
|
||||
function transition(e) {
|
||||
|
|
@ -185,33 +618,105 @@
|
|||
function waiting() {
|
||||
|
||||
}
|
||||
let initing = true
|
||||
configInit()
|
||||
onMounted(() => {
|
||||
init()
|
||||
// setTimeout(()=>{
|
||||
// },500)
|
||||
})
|
||||
watch(() => props.list.length, (newval) => {
|
||||
// #ifdef H5
|
||||
init()
|
||||
// #endif
|
||||
})
|
||||
const nowDanjiPrice = computed(() => {
|
||||
return videoList.value[current.value].price
|
||||
})
|
||||
const rightStyle=computed(()=>{
|
||||
// #ifdef H5
|
||||
return {
|
||||
transform: `translateX(${!control.showControls?'0':60}px)`
|
||||
}
|
||||
// #endif
|
||||
// #ifdef APP
|
||||
return {
|
||||
transform: `translateX(${control.showControls?'0':60}px)`
|
||||
}
|
||||
// #endif
|
||||
})
|
||||
const infoStyle=computed(()=>{
|
||||
// #ifdef H5
|
||||
return {
|
||||
transform: `translateX(${!control.showControls?0:'-110%'})`
|
||||
}
|
||||
// #endif
|
||||
// #ifdef APP
|
||||
return {
|
||||
transform: `translateX(${control.showControls?0:'-110%'})`
|
||||
}
|
||||
// #endif
|
||||
})
|
||||
function loadmore() {
|
||||
console.log('loadmore');
|
||||
}
|
||||
const boxStyle = computed(() => {
|
||||
return {
|
||||
'height': wHeight.value + 'px',
|
||||
'width': '750rpx',
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
<style lang="scss" scoped>
|
||||
.box {
|
||||
/* #ifdef H5 */
|
||||
flex: 1;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.u-flex-1 {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.u-popup {
|
||||
position: fixed !important;
|
||||
}
|
||||
|
||||
::v-deep .u-popup {
|
||||
position: fixed !important;
|
||||
}
|
||||
|
||||
.video {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.poster {
|
||||
/* #ifdef H5 */
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 90%;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
/* #endif */
|
||||
/* #ifdef APP */
|
||||
width: 750rpx;
|
||||
flex: 1;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.u-text-center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.u-flex-row {
|
||||
flex-direction: row !important;
|
||||
}
|
||||
|
||||
.info {
|
||||
width: 80%;
|
||||
height: auto;
|
||||
|
|
@ -223,6 +728,17 @@
|
|||
z-index: 9999;
|
||||
}
|
||||
|
||||
.u-flex-y-center {
|
||||
align-items: center !important;
|
||||
}
|
||||
|
||||
.swipers-items {
|
||||
width: 750rpx;
|
||||
flex: 1;
|
||||
position: relative;
|
||||
background-color: #000;
|
||||
}
|
||||
|
||||
.right {
|
||||
width: 60rpx;
|
||||
position: absolute !important;
|
||||
|
|
@ -246,4 +762,124 @@
|
|||
|
||||
.zhuiju {}
|
||||
}
|
||||
|
||||
.poster-popup {
|
||||
position: fixed !important;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
background-color: rgba(0, 0, 0, 0.6);
|
||||
z-index: 9999;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.ji-list {
|
||||
.ji-item {
|
||||
width: 210rpx;
|
||||
margin-bottom: 20rpx;
|
||||
margin-right: 30rpx;
|
||||
height: 88rpx;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
border-radius: 12rpx;
|
||||
background-color: #F5F7FF;
|
||||
position: relative;
|
||||
|
||||
&.active {
|
||||
background-color: $my-main-color;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
&.mr-0 {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.lock {
|
||||
position: absolute;
|
||||
border-radius: 0px 6px 0px 6px;
|
||||
background-color: #ccc;
|
||||
padding: 2rpx 4rpx;
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.playing {
|
||||
position: absolute;
|
||||
width: 32rpx;
|
||||
height: 24rpx;
|
||||
bottom: 5px;
|
||||
right: 7px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ji-item:nth-of-type(3n) {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.hot {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
}
|
||||
|
||||
.back-icon {
|
||||
position: fixed;
|
||||
z-index: 9999;
|
||||
left: 30rpx;
|
||||
top: 100rpx;
|
||||
}
|
||||
|
||||
.pay-list {
|
||||
.pay-list-item {
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
background-color: #F2F2F2;
|
||||
padding: 24rpx;
|
||||
border-radius: 20rpx;
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.payConfirm {
|
||||
border-radius: 100px;
|
||||
height: 100rpx;
|
||||
line-height: 100rpx;
|
||||
text-align: center;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.zhifubao {
|
||||
width: 56rpx;
|
||||
height: 56rpx;
|
||||
}
|
||||
|
||||
.qrcode {
|
||||
position: fixed;
|
||||
top: -9999px;
|
||||
left: -9999px;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.speed-list {
|
||||
align-items: center;
|
||||
background-color: #eeeeef;
|
||||
padding: 5px 10px;
|
||||
border-radius: 5px;
|
||||
|
||||
.speed-list-item {
|
||||
border-radius: 3px;
|
||||
width: 50px;
|
||||
padding: 8px 0;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
|
||||
&.active {
|
||||
background-color: #ffffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -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;
|
||||
};
|
||||
|
|
@ -73,6 +73,11 @@ function commonsProcess(showLoading, httpReqCallback,isreturm) {
|
|||
isShowErrorToast = true;
|
||||
return Promise.reject(bodyData); // 跳转到catch函数
|
||||
}
|
||||
if (bodyData.code == 500) {
|
||||
// 提示信息
|
||||
isShowErrorToast = true;
|
||||
return Promise.reject(bodyData); // 跳转到catch函数
|
||||
}
|
||||
if (bodyData.code != 0) {
|
||||
infoBox.showToast(data.message);
|
||||
return;
|
||||
|
|
@ -110,7 +115,7 @@ function commonsProcess(showLoading, httpReqCallback,isreturm) {
|
|||
reject();
|
||||
}
|
||||
if (res.code == 500) {
|
||||
infoBox.showErrorToast(res.message || "服务器异常").then(() => {});
|
||||
infoBox.showErrorToast(res.msg || "服务器异常").then(() => {});
|
||||
reject();
|
||||
}
|
||||
reqFinishFunc(); // 请求完毕的动作
|
||||
|
|
|
|||
|
|
@ -20,7 +20,8 @@
|
|||
"modules" : {
|
||||
"Camera" : {},
|
||||
"Push" : {},
|
||||
"VideoPlayer" : {}
|
||||
"VideoPlayer" : {},
|
||||
"Canvas" : "nvue canvas" //使用Canvas模块
|
||||
},
|
||||
/* 应用发布信息 */
|
||||
"distribute" : {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,12 @@
|
|||
<navigator class="more" url="/pages/watching_history/watching_history?type=3">更多</navigator>
|
||||
</view>
|
||||
<view class="list">
|
||||
<view class="item" v-for="item in data.list1" :key="item.id">
|
||||
<view
|
||||
class="item"
|
||||
v-for="item in data.list1"
|
||||
:key="item.id"
|
||||
@click="linkTo(`/pages/video/detail?courseId=${item.courseId}&courseDetailsId=${item.courseDetailsId}`)"
|
||||
>
|
||||
<view class="cover">
|
||||
<image class="img" :src="item.titleImg" mode="aspectFill"></image>
|
||||
<view class="num">{{ item.courseDetailsName }}</view>
|
||||
|
|
@ -26,7 +31,12 @@
|
|||
<navigator class="more" url="/pages/watching_history/watching_history?type=1">更多</navigator>
|
||||
</view>
|
||||
<view class="list">
|
||||
<view class="item" v-for="item in data.list2" :key="item.id">
|
||||
<view
|
||||
class="item"
|
||||
v-for="item in data.list2"
|
||||
:key="item.id"
|
||||
@click="linkTo(`/pages/video/detail?courseId=${item.courseId}&courseDetailsId=${item.courseDetailsId}`)"
|
||||
>
|
||||
<div class="item-content">
|
||||
<view class="cover">
|
||||
<image class="img" :src="item.titleImg" mode="aspectFill"></image>
|
||||
|
|
@ -48,6 +58,7 @@
|
|||
import { reactive } from 'vue';
|
||||
import { selectByUserId } from '@/api/me/me.js';
|
||||
import { onLoad, onPullDownRefresh, onReachBottom } from '@dcloudio/uni-app';
|
||||
import { linkTo } from '@/utils/app.js';
|
||||
|
||||
// 获取数据
|
||||
async function selectByUserIdAjax() {
|
||||
|
|
|
|||
|
|
@ -25,11 +25,9 @@
|
|||
})
|
||||
|
||||
function seVideo(item) {
|
||||
// uni.navigateTo({
|
||||
// url: '/me/detail/detail?id=' + item.courseId + '&courseDetailsId=' + item.courseDetailsId +
|
||||
// '&tt_album_id=' + item.dyCourseId + '&tt_episode_id=' + item
|
||||
// .dyEpisodeId
|
||||
// })
|
||||
uni.navigateTo({
|
||||
url:"/pages/video/detail?courseId="+item.courseId+"&courseDetailsId="+item.courseDetailsId
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -54,166 +54,174 @@
|
|||
|
||||
</template>
|
||||
<script setup>
|
||||
import {
|
||||
reactive,
|
||||
watch
|
||||
} from "vue";
|
||||
import {
|
||||
onShow, onReachBottom
|
||||
} from '@dcloudio/uni-app'
|
||||
const props = defineProps({
|
||||
list: {
|
||||
type: Array,
|
||||
default: []
|
||||
},
|
||||
})
|
||||
let datas = reactive({
|
||||
arrListLeft: [], //左边数据
|
||||
arrListRight: [], //右边数据
|
||||
})
|
||||
onShow(() => {
|
||||
spliceArrayListr()
|
||||
})
|
||||
watch(() => props.list, () => {
|
||||
spliceArrayListr()
|
||||
})
|
||||
function spliceArrayListr() {
|
||||
datas.arrListRight = []
|
||||
datas.arrListLeft = []
|
||||
props.list.map((item, index) => {
|
||||
if (index % 2 === 0) {
|
||||
datas.arrListLeft.push(item)
|
||||
} else {
|
||||
datas.arrListRight.push(item)
|
||||
}
|
||||
import {
|
||||
reactive,
|
||||
watch
|
||||
} from "vue";
|
||||
import {
|
||||
onShow,
|
||||
onReachBottom
|
||||
} from '@dcloudio/uni-app'
|
||||
const props = defineProps({
|
||||
list: {
|
||||
type: Array,
|
||||
default: []
|
||||
},
|
||||
})
|
||||
}
|
||||
let datas = reactive({
|
||||
arrListLeft: [], //左边数据
|
||||
arrListRight: [], //右边数据
|
||||
})
|
||||
onShow(() => {
|
||||
spliceArrayListr()
|
||||
})
|
||||
watch(() => props.list, () => {
|
||||
spliceArrayListr()
|
||||
})
|
||||
|
||||
function clickItem(item) {
|
||||
uni.navigateTo({
|
||||
url: "/pages/video/detail?courseId=" + item.courseId + "&courseDetailsId=" + item.courseDetailsId
|
||||
})
|
||||
}
|
||||
|
||||
function spliceArrayListr() {
|
||||
datas.arrListRight = []
|
||||
datas.arrListLeft = []
|
||||
props.list.map((item, index) => {
|
||||
if (index % 2 === 0) {
|
||||
datas.arrListLeft.push(item)
|
||||
} else {
|
||||
datas.arrListRight.push(item)
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.list {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.list-box {
|
||||
width: 686rpx;
|
||||
height: 100%;
|
||||
.list {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.list-box-ite {
|
||||
width: calc((100% - 20rpx) / 2);
|
||||
height: auto;
|
||||
}
|
||||
.list-box {
|
||||
width: 686rpx;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.list-box-ite-item {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
margin-bottom: 20rpx;
|
||||
.list-box-ite {
|
||||
width: calc((100% - 20rpx) / 2);
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.list-box-ite-item-img {
|
||||
.list-box-ite-item {
|
||||
width: 100%;
|
||||
border-radius: 24rpx 24rpx 0 0;
|
||||
min-height: 300rpx;
|
||||
position: relative;
|
||||
height: auto;
|
||||
margin-bottom: 20rpx;
|
||||
|
||||
image {
|
||||
.list-box-ite-item-img {
|
||||
width: 100%;
|
||||
min-height: 300rpx;
|
||||
border-radius: 24rpx 24rpx 0 0;
|
||||
min-height: 300rpx;
|
||||
position: relative;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
min-height: 300rpx;
|
||||
border-radius: 24rpx 24rpx 0 0;
|
||||
}
|
||||
|
||||
.list-box-ite-item-img-t {
|
||||
position: absolute;
|
||||
bottom: 10rpx;
|
||||
right: 0;
|
||||
max-width: 80%;
|
||||
border-radius: 10rpx;
|
||||
background-color: rgba(51, 51, 51, 0.7);
|
||||
color: #FFFFFF;
|
||||
font-size: 22rpx;
|
||||
padding: 10rpx;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.list-box-ite-item-img-t {
|
||||
position: absolute;
|
||||
bottom: 10rpx;
|
||||
right: 0;
|
||||
max-width: 80%;
|
||||
border-radius: 10rpx;
|
||||
background-color: rgba(51, 51, 51, 0.7);
|
||||
color: #FFFFFF;
|
||||
.list-box-ite-item-txt {
|
||||
padding: 10rpx 20rpx;
|
||||
background-color: #ffffff;
|
||||
border-radius: 0 0 24rpx 24rpx;
|
||||
}
|
||||
|
||||
.list-box-ite-item-txt-t {
|
||||
color: #333333;
|
||||
font-size: 30rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.list-box-ite-item-txt-l {
|
||||
color: #999999;
|
||||
font-size: 22rpx;
|
||||
padding: 10rpx;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
|
||||
margin-top: 10rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.list-box-ite-item-txt {
|
||||
padding: 10rpx 20rpx;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.list-box-item {
|
||||
width: calc((100% - 20rpx) / 2);
|
||||
// height: 100%;
|
||||
min-height: 320rpx;
|
||||
border-radius: 24rpx;
|
||||
background-color: #ffffff;
|
||||
border-radius: 0 0 24rpx 24rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.list-box-ite-item-txt-t {
|
||||
color: #333333;
|
||||
font-size: 30rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.list-box-ite-item-txt-l {
|
||||
color: #999999;
|
||||
font-size: 22rpx;
|
||||
margin-top: 10rpx;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.list-box-item {
|
||||
width: calc((100% - 20rpx) / 2);
|
||||
// height: 100%;
|
||||
min-height: 320rpx;
|
||||
border-radius: 24rpx;
|
||||
background-color: #ffffff;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.list-box-item-img {
|
||||
width: 100%;
|
||||
height: 200rpx;
|
||||
border-radius: 24rpx 24rpx 0 0;
|
||||
|
||||
image {
|
||||
.list-box-item-img {
|
||||
width: 100%;
|
||||
height: 200rpx;
|
||||
border-radius: 24rpx 24rpx 0 0;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: 200rpx;
|
||||
border-radius: 24rpx 24rpx 0 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
.list-box-item-txt {
|
||||
width: 100%;
|
||||
// height: 120rpx;
|
||||
padding: 20rpx 0;
|
||||
border-radius: 0 0 24rpx 24rpx;
|
||||
}
|
||||
|
||||
.list-box-item-txt {
|
||||
width: 100%;
|
||||
// height: 120rpx;
|
||||
padding: 20rpx 0;
|
||||
border-radius: 0 0 24rpx 24rpx;
|
||||
}
|
||||
.list-box-item-txt-t {
|
||||
width: 100%;
|
||||
padding: 0 20rpx;
|
||||
color: #333333;
|
||||
font-size: 30rpx;
|
||||
font-weight: bold;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.list-box-item-txt-t {
|
||||
width: 100%;
|
||||
padding: 0 20rpx;
|
||||
color: #333333;
|
||||
font-size: 30rpx;
|
||||
font-weight: bold;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
.list-box-item-txt-l {
|
||||
color: #999999;
|
||||
font-size: 22rpx;
|
||||
margin-top: 10rpx;
|
||||
padding: 0 20rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.list-box-item-txt-l {
|
||||
color: #999999;
|
||||
font-size: 22rpx;
|
||||
margin-top: 10rpx;
|
||||
padding: 0 20rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -54,7 +54,12 @@
|
|||
</view>
|
||||
</navigator>
|
||||
<view class="history-list">
|
||||
<view class="item" v-for="item in recordThree" :key="item.id">
|
||||
<view
|
||||
class="item"
|
||||
v-for="item in recordThree"
|
||||
:key="item.id"
|
||||
@click="linkTo(`/pages/video/detail?courseId=${item.courseId}&courseDetailsId=${item.courseDetailsId}`)"
|
||||
>
|
||||
<image class="cover" :src="item.titleImg" mode="aspectFill"></image>
|
||||
<view class="name">{{ item.title }}</view>
|
||||
<view class="t">看到{{ item.courseDetailsName }}</view>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<template>
|
||||
<view class="min-page">
|
||||
<my-video-list @swiperChange="swiperChange" :list="state.list" :isCollect="state.isCollect" @share="share"
|
||||
<my-video-list v-if="state.list.length" @swiperChange="swiperChange" :list="state.list" @update="update"
|
||||
:info="state"
|
||||
></my-video-list>
|
||||
</view>
|
||||
</template>
|
||||
|
|
@ -17,6 +18,9 @@
|
|||
import {
|
||||
slice
|
||||
} from 'lodash'
|
||||
const boxStyle={
|
||||
height:'835px'
|
||||
}
|
||||
let options = {}
|
||||
const state = reactive({
|
||||
collect: 0,
|
||||
|
|
@ -26,9 +30,22 @@
|
|||
title: ''
|
||||
})
|
||||
async function init() {
|
||||
const res = await Api.getVideoDetail(options)
|
||||
Object.assign(state, res)
|
||||
state.list = res.list
|
||||
try {
|
||||
const res = await Api.getVideoDetail(options)
|
||||
Object.assign(state, res)
|
||||
state.list = res.list
|
||||
} catch (error) {
|
||||
// if(getCurrentPages().length>=2){
|
||||
// uni.navigateBack()
|
||||
// }else{
|
||||
// uni.switchTab({
|
||||
// url:'/pages/index/index'
|
||||
// })
|
||||
// }
|
||||
}
|
||||
}
|
||||
function update({index,item}){
|
||||
state.list[index]=item
|
||||
}
|
||||
onLoad((opt) => {
|
||||
Object.assign(options, opt)
|
||||
|
|
@ -54,4 +71,8 @@
|
|||
background-color: #000;
|
||||
overflow: hidden;
|
||||
}
|
||||
.u-popup{
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
<template>
|
||||
<view class="min-page " >
|
||||
<!-- <up-button @click="toDetail">toDetail</up-button> -->
|
||||
<my-video-list isCommand isTabbar v-if="state.list.length" @swiperChange="swiperChange" :list="state.list" @update="update"
|
||||
:info="state"
|
||||
></my-video-list>
|
||||
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
onLoad,
|
||||
onShow
|
||||
} from '@dcloudio/uni-app'
|
||||
import * as Api from '@/api/video/index.js'
|
||||
import {
|
||||
computed,
|
||||
reactive,
|
||||
ref
|
||||
} from 'vue'
|
||||
import {
|
||||
slice
|
||||
} from 'lodash'
|
||||
|
||||
|
||||
function toDetail() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/video/detail?courseId=1208'
|
||||
})
|
||||
}
|
||||
let options = {}
|
||||
const state = reactive({
|
||||
collect: 0,
|
||||
current: {},
|
||||
list: [],
|
||||
price: 0,
|
||||
title: ''
|
||||
})
|
||||
async function init() {
|
||||
const res = await Api.tuijianVideo(options)
|
||||
state.current = res.list[0]
|
||||
Object.assign(state, res)
|
||||
state.list = res.list
|
||||
}
|
||||
|
||||
function update({
|
||||
index,
|
||||
item
|
||||
}) {
|
||||
state.list[index] = item
|
||||
}
|
||||
onLoad((opt) => {
|
||||
Object.assign(options, opt)
|
||||
init()
|
||||
})
|
||||
|
||||
function swiperChange({
|
||||
current,
|
||||
direction,
|
||||
data
|
||||
}) {}
|
||||
|
||||
onShow(() => {
|
||||
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
page{
|
||||
height: calc(100vh - 50px);
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
<style lang="scss" scoped>
|
||||
.min-page {
|
||||
/* #ifdef H5 */
|
||||
height: calc(100vh - 50px);
|
||||
/* #endif */
|
||||
/* #ifdef APP */
|
||||
height: 100vh;
|
||||
/* #endif */
|
||||
background-color: #000;
|
||||
overflow: hidden;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.u-popup {
|
||||
position: fixed;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
<template>
|
||||
<view class="u-p-60">
|
||||
<up-button @click="toDetail">toDetail</up-button>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
function toDetail(){
|
||||
uni.navigateTo({
|
||||
url:'/pages/video/detail'
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
|
|
@ -1,7 +1,8 @@
|
|||
<template>
|
||||
<view class="container">
|
||||
<view class="list">
|
||||
<view class="item" v-for="item in listData.list" :key="item.id">
|
||||
<view class="item" v-for="item in listData.list" :key="item.id"
|
||||
@click="linkTo(`/pages/video/detail?courseId=${item.courseId}&courseDetailsId=${item.courseDetailsId}`)">
|
||||
<view class="cover">
|
||||
<image class="img" :src="item.titleImg" mode="aspectFill"></image>
|
||||
</view>
|
||||
|
|
@ -27,6 +28,7 @@
|
|||
<script setup>
|
||||
import { ref, reactive } from 'vue';
|
||||
import { onLoad, onReachBottom, onPullDownRefresh } from '@dcloudio/uni-app';
|
||||
import { linkTo } from '@/utils/app.js';
|
||||
|
||||
import { selectByUserId } from '@/api/me/me.js';
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 3.0 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 5.7 KiB |
3
uni.scss
3
uni.scss
|
|
@ -77,3 +77,6 @@ $uni-font-size-subtitle: 26px;
|
|||
$uni-color-paragraph: #3f536e; // 文章段落颜色
|
||||
$uni-font-size-paragraph: 15px;
|
||||
@import 'uview-plus/theme.scss';
|
||||
|
||||
$my-main-color:#ff7581;
|
||||
$my-red-color:#F02C45;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
## 3.0.8(2024-10-03)
|
||||
组件优化
|
||||
## 3.0.6(2024-07-14)
|
||||
组件优化
|
||||
## 3.0.2(2023-07-29)
|
||||
组件优化
|
||||
## 3.0.1(2023-07-28)
|
||||
组件说明优化
|
||||
## 3.0(2023-07-22)
|
||||
优化使用说明,小程序设置网络图片地址,需要是服务器白名单IP,本地图片无限制
|
||||
## 2.0.1(2023-07-11)
|
||||
兼容微信小程序 优化使用说明
|
||||
## 2.0(2023-07-11)
|
||||
组件优化, 兼容小程序
|
||||
## 1.0.1(2023-07-11)
|
||||
组件优化
|
||||
## 1.0.0(2023-07-02)
|
||||
组件初始化
|
||||
|
|
@ -0,0 +1,447 @@
|
|||
<template>
|
||||
<view>
|
||||
<!-- 绘制canvas -->
|
||||
<canvas class="mycanvas" canvas-id="mycanvas" :style="'width:' + (windowWidth-60) + 'px;height:520px'"></canvas>
|
||||
|
||||
<block>
|
||||
<image class="imgs" :style="'width:' + (windowWidth-60) + 'px;height:520px'" :src="imgUrl" mode=""></image>
|
||||
</block>
|
||||
|
||||
|
||||
<!-- #ifndef H5 -->
|
||||
<view class="saveImg" @tap="saveImg" :style="'background:' + colors">
|
||||
保存图片
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef H5 -->
|
||||
<p class="tips">长按图片进行保存</p>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import uQRCode from './uqrcode.js'
|
||||
|
||||
export default {
|
||||
mixins: [{
|
||||
methods: {
|
||||
setData: function(obj, callback) {
|
||||
let that = this;
|
||||
const handleData = (tepData, tepKey, afterKey) => {
|
||||
tepKey = tepKey.split('.');
|
||||
tepKey.forEach(item => {
|
||||
if (tepData[item] === null || tepData[item] === undefined) {
|
||||
let reg = /^[0-9]+$/;
|
||||
tepData[item] = reg.test(afterKey) ? [] : {};
|
||||
tepData = tepData[item];
|
||||
} else {
|
||||
tepData = tepData[item];
|
||||
}
|
||||
});
|
||||
return tepData;
|
||||
};
|
||||
const isFn = function(value) {
|
||||
return typeof value == 'function' || false;
|
||||
};
|
||||
Object.keys(obj).forEach(function(key) {
|
||||
let val = obj[key];
|
||||
key = key.replace(/\]/g, '').replace(/\[/g, '.');
|
||||
let front, after;
|
||||
let index_after = key.lastIndexOf('.');
|
||||
if (index_after != -1) {
|
||||
after = key.slice(index_after + 1);
|
||||
front = handleData(that, key.slice(0, index_after), after);
|
||||
} else {
|
||||
after = key;
|
||||
front = that;
|
||||
}
|
||||
if (front.$data && front.$data[after] === undefined) {
|
||||
Object.defineProperty(front, after, {
|
||||
get() {
|
||||
return front.$data[after];
|
||||
},
|
||||
set(newValue) {
|
||||
front.$data[after] = newValue;
|
||||
that.$forceUpdate();
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
front[after] = val;
|
||||
} else {
|
||||
that.$set(front, after, val);
|
||||
}
|
||||
});
|
||||
isFn(callback) && this.$nextTick(callback);
|
||||
}
|
||||
}
|
||||
}],
|
||||
data() {
|
||||
return {
|
||||
windowWidth: '',
|
||||
windowHeight: '',
|
||||
colors: "#fa436a",
|
||||
ctx: '',
|
||||
imgUrl: '',
|
||||
isShow: false,
|
||||
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
props: {
|
||||
// 海报生成数据
|
||||
posterData: {
|
||||
type: Object
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getSystem();
|
||||
|
||||
this.setPoster();
|
||||
},
|
||||
/**
|
||||
* 页面上拉触底事件的处理函数
|
||||
*/
|
||||
onReachBottom: function() {},
|
||||
|
||||
/**
|
||||
* 用户点击右上角分享
|
||||
*/
|
||||
onShareAppMessage: function() {},
|
||||
methods: {
|
||||
getSystem() {
|
||||
let that = this;
|
||||
uni.getSystemInfo({
|
||||
success: function(res) {
|
||||
console.log(res);
|
||||
that.setData({
|
||||
windowHeight: res.windowHeight,
|
||||
windowWidth: res.windowWidth
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
setPoster() {
|
||||
uni.showLoading({
|
||||
title: '海报生成中...'
|
||||
})
|
||||
let ctx = uni.createCanvasContext('mycanvas', this); // 绘制背景
|
||||
ctx.fillStyle = "#FFFFFF"
|
||||
ctx.fillRect(0, 0, this.windowWidth - 60, 520)
|
||||
/**
|
||||
* 绘制名称
|
||||
*/
|
||||
// const setText = (context, fs, color, x, y, c, bold) => {
|
||||
// context.setFillStyle(color);
|
||||
// context.setTextAlign('left');
|
||||
// if (bold) {
|
||||
// context.font = 'normal bold 20px Arial,sans-serif';
|
||||
// } else {
|
||||
// context.font = 'normal 20px Arial,sans-serif';
|
||||
// }
|
||||
// context.setFontSize(fs);
|
||||
// context.fillText(c, x, y);
|
||||
// context.restore();
|
||||
// };
|
||||
// setText(ctx, 14, '#333', 85, 35, this.posterData.name, 'bold');
|
||||
// setText(ctx, 12, '#999', 85, 58, '为您挑选了一个好礼物');
|
||||
// ctx.save();
|
||||
/**
|
||||
* 绘制头像
|
||||
*/
|
||||
// ctx.beginPath();
|
||||
// let avatar_width = 60; //头像宽度
|
||||
// let avatar_height = 60; //头像高度
|
||||
// let avatar_x = 15; //头像的x坐标
|
||||
// let avatar_y = 15; //头像的y坐标
|
||||
// let radius = 8 //头像的圆角弧度
|
||||
// // 绘制圆角头像
|
||||
// this.setRadius(ctx, avatar_width, avatar_height, avatar_x, avatar_y, radius)
|
||||
// 绘制圆形图片
|
||||
// this.setCircular(ctx, avatar_width, avatar_height, avatar_x, avatar_y)
|
||||
|
||||
// 绘制商品图片
|
||||
this.setGoodsImg(ctx)
|
||||
|
||||
// 绘制商品价格
|
||||
let pirce = '¥ ' + this.posterData.money
|
||||
// this.setGoodsPrice(ctx, 20, this.colors, 15, 410, pirce)
|
||||
// 绘制商品名称
|
||||
this.setGoodsName(ctx)
|
||||
|
||||
},
|
||||
|
||||
setEwm(ctx) {
|
||||
|
||||
|
||||
console.log('生成二维码')
|
||||
let code_widht = 100; //二维码宽度
|
||||
let code_height = 100; //二维码高度
|
||||
let x = this.windowWidth - 170
|
||||
|
||||
|
||||
let myThis = this;
|
||||
console.log(this.windowWidth);
|
||||
|
||||
|
||||
uQRCode.make({
|
||||
canvasId: 'mycanvas',
|
||||
componentInstance: this,
|
||||
text: this.posterData.url,
|
||||
size: 200,
|
||||
margin: 10,
|
||||
fileType: 'png',
|
||||
success: res => {
|
||||
console.log('生成二维码3')
|
||||
|
||||
console.log('res = ' + res);
|
||||
|
||||
ctx.drawImage(res, x, 410, code_widht, code_height);
|
||||
|
||||
setTimeout(() => { //必须延时执行 不然h5不显示
|
||||
ctx.save();
|
||||
ctx.draw(false, () => {
|
||||
setTimeout(() => {
|
||||
uni.canvasToTempFilePath({
|
||||
canvasId: 'mycanvas',
|
||||
success: (res) => {
|
||||
console.log(res)
|
||||
this.imgUrl = res.tempFilePath
|
||||
}
|
||||
}, this)
|
||||
}, 300)
|
||||
})
|
||||
uni.hideLoading()
|
||||
}, 1000)
|
||||
|
||||
},
|
||||
complete: () => {
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
},
|
||||
setRadius(ctx, avatar_width, avatar_height, avatar_x, avatar_y, radius) {
|
||||
/**
|
||||
* 绘制圆角
|
||||
*/
|
||||
ctx.arc(avatar_x + radius, avatar_y + radius, radius, Math.PI, Math.PI * 3 / 2);
|
||||
ctx.lineTo(avatar_width - radius + avatar_x, avatar_y);
|
||||
ctx.arc(avatar_width - radius + avatar_x, radius + avatar_y, radius, Math.PI * 3 / 2, Math.PI * 2);
|
||||
ctx.lineTo(avatar_width + avatar_x, avatar_height + avatar_y - radius);
|
||||
ctx.arc(avatar_width - radius + avatar_x, avatar_height - radius + avatar_y, radius, 0, Math.PI * 1 / 2);
|
||||
ctx.lineTo(radius + avatar_x, avatar_height + avatar_y);
|
||||
ctx.arc(radius + avatar_x, avatar_height - radius + avatar_y, radius, Math.PI * 1 / 2, Math.PI);
|
||||
// 开始填充
|
||||
ctx.strokeStyle = "#fff";
|
||||
ctx.fill() //保证图片无bug填充
|
||||
ctx.clip(); //画了圆 再剪切 原始画布中剪切任意形状和尺寸。一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内
|
||||
|
||||
ctx.drawImage(this.posterData.logo, avatar_x, avatar_y, avatar_width, avatar_height);
|
||||
ctx.closePath()
|
||||
ctx.restore();
|
||||
},
|
||||
setCircular(ctx, avatar_width, avatar_height, avatar_x, avatar_y) { //绘制圆形图片
|
||||
/**
|
||||
* 绘制圆形
|
||||
*/
|
||||
//先画个圆 前两个参数确定了圆心 (x,y) 坐标 第三个参数是圆的半径 四参数是绘图方向 默认是false,即顺时针
|
||||
ctx.arc(avatar_width / 2 + avatar_x, avatar_height / 2 + avatar_y, avatar_width / 2, 0, Math.PI * 2,
|
||||
false); //画圆
|
||||
// 开始填充
|
||||
ctx.strokeStyle = "#fff";
|
||||
ctx.fill() //保证图片无bug填充
|
||||
ctx.clip(); //画了圆 再剪切 原始画布中剪切任意形状和尺寸。一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内
|
||||
|
||||
ctx.drawImage(this.posterData.logo, avatar_x, avatar_y, avatar_width, avatar_height);
|
||||
ctx.closePath()
|
||||
ctx.restore();
|
||||
},
|
||||
setGoodsImg(ctx) { //绘制中间商品图片
|
||||
let width = this.windowWidth - 90
|
||||
ctx.drawImage(this.posterData.img, 15, 15, width, width);
|
||||
ctx.save();
|
||||
},
|
||||
setGoodsPrice(ctx, fs, color, x, y, c, bold) { //绘制商品价格
|
||||
ctx.setFillStyle(color);
|
||||
ctx.setTextAlign('left');
|
||||
if (bold) {
|
||||
ctx.font = 'normal bold 20px Arial,sans-serif';
|
||||
} else {
|
||||
ctx.font = 'normal 20px Arial,sans-serif';
|
||||
}
|
||||
ctx.setFontSize(fs);
|
||||
ctx.fillText(c, x, y);
|
||||
ctx.restore();
|
||||
},
|
||||
setGoodsName(ctx) { //绘制商品名称
|
||||
let obj = {
|
||||
x: 20, //绘制文本的左上角x坐标位置
|
||||
y: 440, //绘制文本的左上角y坐标位置
|
||||
width: 210,
|
||||
height: 20,
|
||||
line: 2,
|
||||
color: '#202020',
|
||||
size: 14, //字体的字号
|
||||
align: 'left',
|
||||
baseline: 'top',
|
||||
text: this.posterData.title,
|
||||
bold: true
|
||||
};
|
||||
var td = Math.ceil(obj.width / (obj.size));
|
||||
var tr = Math.ceil(obj.text.length / td);
|
||||
for (var i = 0; i < tr; i++) {
|
||||
var txt = {
|
||||
x: obj.x,
|
||||
y: obj.y + (i * obj.height),
|
||||
color: obj.color,
|
||||
size: obj.size,
|
||||
align: obj.align,
|
||||
baseline: obj.baseline,
|
||||
text: obj.text.substring(i * td, (i + 1) * td),
|
||||
bold: obj.bold
|
||||
};
|
||||
if (i < obj.line) {
|
||||
if (i == obj.line - 1) {
|
||||
txt.text = txt.text.substring(0, txt.text.length - 3) + '......';
|
||||
}
|
||||
this.drawText(ctx, txt);
|
||||
}
|
||||
}
|
||||
// 绘制二维码
|
||||
this.setEwm(ctx);
|
||||
},
|
||||
/**
|
||||
* 渲染文字
|
||||
*
|
||||
* @param {Object} obj
|
||||
*/
|
||||
drawText: function(ctx, obj) {
|
||||
console.log('渲染文字', obj)
|
||||
ctx.save();
|
||||
ctx.setFillStyle(obj.color);
|
||||
ctx.setFontSize(obj.size);
|
||||
ctx.setTextAlign(obj.align);
|
||||
ctx.setTextBaseline(obj.baseline);
|
||||
if (obj.bold) {
|
||||
console.log('字体加粗')
|
||||
ctx.fillText(obj.text, obj.x, obj.y - 0.1);
|
||||
ctx.fillText(obj.text, obj.x - 0.1, obj.y);
|
||||
}
|
||||
ctx.fillText(obj.text, obj.x, obj.y);
|
||||
if (obj.bold) {
|
||||
ctx.fillText(obj.text, obj.x, obj.y + 0.1);
|
||||
ctx.fillText(obj.text, obj.x + 0.1, obj.y);
|
||||
}
|
||||
ctx.restore();
|
||||
},
|
||||
saveImg() {
|
||||
//保存图片
|
||||
uni.showLoading({
|
||||
title: '保存中...'
|
||||
});
|
||||
let that = this;
|
||||
// #ifdef MP
|
||||
uni.getSetting({
|
||||
success(res) {
|
||||
uni.hideLoading();
|
||||
console.log(res)
|
||||
if (!res.authSetting['scope.writePhotosAlbum']) {
|
||||
wx.authorize({
|
||||
scope: 'scope.writePhotosAlbum',
|
||||
success: (res) => {
|
||||
console.log(res)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
setTimeout(() => {
|
||||
uni.saveImageToPhotosAlbum({
|
||||
filePath: that.imgUrl,
|
||||
success(re) {
|
||||
uni.hideLoading();
|
||||
uni.showToast({
|
||||
title: '保存成功',
|
||||
icon: 'success'
|
||||
});
|
||||
},
|
||||
fail(err) {
|
||||
console.log(err);
|
||||
uni.showToast({
|
||||
title: '保存失败',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
// #endif
|
||||
// #ifdef APP-PLUS
|
||||
setTimeout(() => {
|
||||
uni.saveImageToPhotosAlbum({
|
||||
filePath: that.imgUrl,
|
||||
success(re) {
|
||||
uni.hideLoading();
|
||||
uni.showToast({
|
||||
title: '保存成功',
|
||||
icon: 'success'
|
||||
});
|
||||
},
|
||||
fail(err) {
|
||||
console.log(err);
|
||||
uni.showToast({
|
||||
title: '保存失败',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
}, 1000);
|
||||
// #endif
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style scoped>
|
||||
.mycanvas {
|
||||
margin: 0 auto;
|
||||
border-radius: 10upx;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.saveImg {
|
||||
width: 70%;
|
||||
height: 80upx;
|
||||
line-height: 80upx;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
background-color: #4DB8E4;
|
||||
border-radius: 10upx;
|
||||
margin: 40upx auto 20upx;
|
||||
}
|
||||
|
||||
.imgs {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 50%;
|
||||
border-radius: 10upx;
|
||||
transform: translateX(-50%);
|
||||
/* 遮挡二维码 */
|
||||
background-color: white;
|
||||
/* 置于上层 */
|
||||
z-index: 99;
|
||||
}
|
||||
|
||||
.tips {
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
font-size: 24upx;
|
||||
margin-top: 20upx;
|
||||
}
|
||||
</style>
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,86 @@
|
|||
{
|
||||
"id": "cc-beautyPoster",
|
||||
"displayName": "一款基于canvas的精美商品海报生成组件 根据个性化数据生成商品海报图 长按保存图片",
|
||||
"version": "3.0.8",
|
||||
"description": "一款基于canvas的精美商品海报生成组件 根据个性化数据生成商品海报图 长按保存图片",
|
||||
"keywords": [
|
||||
"海报",
|
||||
"canvas",
|
||||
"商品海报",
|
||||
"朋友圈海报",
|
||||
"海报生成"
|
||||
],
|
||||
"repository": "",
|
||||
"engines": {
|
||||
"HBuilderX": "^3.8.0"
|
||||
},
|
||||
"dcloudext": {
|
||||
"type": "component-vue",
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "无",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": ""
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y",
|
||||
"alipay": "n"
|
||||
},
|
||||
"client": {
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
},
|
||||
"App": {
|
||||
"app-vue": "y",
|
||||
"app-nvue": "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",
|
||||
"飞书": "y",
|
||||
"京东": "y"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "y",
|
||||
"联盟": "y"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,170 @@
|
|||
# cc-beautyPoster
|
||||
|
||||
|
||||
|
||||
##uniapp专属精品组件页面模板(由前端组件开发出品)精品组件页面模板
|
||||
|
||||
###●组件模板规划:
|
||||
由前端组件开发出品的精品组件页面模板,将陆续发布,预计高达约几百种供您使用,是快速快发项目、创业的必备精品。
|
||||
|
||||
合集地址: uni-app模板合集地址:(https://ext.dcloud.net.cn/publisher?id=274945) 如查看全部页面模板,请前往上述uniapp插件市场合集地址;
|
||||
|
||||
###●组件模板效果图:
|
||||
可下载项目后预览,效果图见右侧图片;
|
||||
|
||||
###●组件模板费用:
|
||||
学习:免费下载,进行学习,无费用;
|
||||
|
||||
使用/商用:本页面地址赞赏10元后,可终身商用;
|
||||
|
||||
###●组件模板使用版权/商用:
|
||||
本组件模板免费下载可供学习,如需使用及商用,请在本组件页面模板进行赞赏10元
|
||||
|
||||
(仅需10元获取精品页面模板代码-物有所值,1个组件页面市场价100元 )
|
||||
|
||||
赞赏10后(当前项目产生赞赏订单可追溯)即可终身商用当前本地址下载的页面模版代码,不同下载地址需进行不同的赞赏。(不赞赏就进行商用使用者,面临侵权!保留追究知识产权法律责任!后果自负!)
|
||||
|
||||
|
||||
### 我的技术公众号(私信可加前端技术交流群)
|
||||
|
||||
群内气氛挺不错的,应该或许可能大概,算是为数不多的,专搞技术的前端群,偶尔聊天摸鱼
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
#### 使用方法
|
||||
```使用方法
|
||||
|
||||
<!-- posterData: 海报数据 -->
|
||||
<cc-beautyPoster :posterData="posterData"></cc-beautyPoster>
|
||||
|
||||
<!-- 海报数据字段 注意小程序下网络图片地址需要是服务器设置的白名单地址 本地图片无限制! -->
|
||||
posterData: {
|
||||
// 用户姓名
|
||||
name: '小明',
|
||||
// 用户头像
|
||||
logo: '/static/images/headIcon.jpg',
|
||||
// 商品名称
|
||||
title: '精美时尚苹果手机一部',
|
||||
// 商品价格
|
||||
money: '5200.90',
|
||||
// 商品图片(小程序需要换成自己服务器白名单设置的地址)
|
||||
img: '/static/images/goods.jpg',
|
||||
// 商品链接
|
||||
url: 'https://www.apple.com.cn/iphone/'
|
||||
|
||||
|
||||
},
|
||||
|
||||
```
|
||||
|
||||
#### HTML代码实现部分
|
||||
```html
|
||||
<template>
|
||||
<view class="content">
|
||||
|
||||
<button style="margin-top: 38px;" @click="openPoster">生成商品海报</button>
|
||||
|
||||
<!-- 海报弹框 -->
|
||||
<uni-popup ref="popup" type="center">
|
||||
<view class="center_poter" style="margin: 0 auto;" v-if="shows">
|
||||
<!-- #ifndef MP -->
|
||||
<image class="close_btn" src="/static/images/goods/close.png" @click="hidePoster">
|
||||
</image>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef MP -->
|
||||
<cover-image class="close_btn" src="/static/images/goods/close.png" @click="hidePoster">
|
||||
</cover-image>
|
||||
<!-- #endif -->
|
||||
|
||||
<!-- posterData: 海报数据 -->
|
||||
<cc-beautyPoster :posterData="posterData"></cc-beautyPoster>
|
||||
</view>
|
||||
</uni-popup>
|
||||
|
||||
</view>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import uniPopup from '@/components/uni-popup/uni-popup.vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
uniPopup
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
shows: false,
|
||||
posterData: {
|
||||
// 用户姓名
|
||||
name: '小明',
|
||||
// 用户头像
|
||||
logo: '/static/images/headIcon.jpg',
|
||||
// 商品名称
|
||||
title: '精美时尚苹果手机一部',
|
||||
// 商品价格
|
||||
money: '5200.90',
|
||||
// 商品图片(小程序需要换成自己服务器白名单设置的地址)
|
||||
img: '/static/images/goods.jpg',
|
||||
// 商品链接
|
||||
url: 'https://www.apple.com.cn/iphone/'
|
||||
|
||||
},
|
||||
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
//生成海报
|
||||
openPoster() {
|
||||
this.shows = false
|
||||
uni.showLoading({
|
||||
title: '海报绘制中..'
|
||||
})
|
||||
this.$refs.popup.open()
|
||||
setTimeout(() => {
|
||||
uni.hideLoading()
|
||||
this.shows = true
|
||||
}, 400)
|
||||
},
|
||||
|
||||
//关闭海报
|
||||
hidePoster() {
|
||||
this.$refs.popup.close()
|
||||
},
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
}
|
||||
|
||||
.center_poter {
|
||||
position: relative;
|
||||
z-index: 999;
|
||||
|
||||
.close_btn {
|
||||
width: 40upx;
|
||||
height: 40upx;
|
||||
background-color: rgba($color: #000000, $alpha: .3);
|
||||
position: absolute;
|
||||
top: 5upx;
|
||||
right: 5upx;
|
||||
z-index: 500;
|
||||
padding: 5upx;
|
||||
border-radius: 6upx;
|
||||
z-index: 999;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
|
@ -1,3 +1,39 @@
|
|||
export function isEmpty(val){
|
||||
return val===null||val===undefined||val===''
|
||||
}
|
||||
|
||||
import {
|
||||
getCurrentInstance,
|
||||
} from 'vue';
|
||||
export async function getElRect(elClass, instance,option) {
|
||||
instance = instance ? instance : getCurrentInstance();
|
||||
const query = uni.createSelectorQuery().in(instance.proxy);
|
||||
try{
|
||||
const res= await getEle(query,elClass,option)
|
||||
return res
|
||||
}catch(e){
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
async function getEle(query,elClass,option){
|
||||
return new Promise((resolve, reject)=>{
|
||||
query.select('.' + elClass).fields({
|
||||
size: true,
|
||||
...option
|
||||
}, res => {
|
||||
// 如果节点尚未生成,res值为null,循环调用执行
|
||||
if (!res) {
|
||||
return setTimeout(() => {
|
||||
getEle(query,elClass,option);
|
||||
}, 10);
|
||||
}
|
||||
resolve(res);
|
||||
}).exec();
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
export async function getSafeBottomHeight(className, height = 16) {
|
||||
const bottomEle = await getElRect(className)
|
||||
return bottomEle.height + height
|
||||
}
|
||||
Loading…
Reference in New Issue