init
This commit is contained in:
40
xhs-mini-demos/component-case/camera/camera.css
Normal file
40
xhs-mini-demos/component-case/camera/camera.css
Normal file
@@ -0,0 +1,40 @@
|
||||
/* @import '../../../common/lib/weui.css'; */
|
||||
|
||||
camera {
|
||||
height: 250px;
|
||||
}
|
||||
|
||||
.preview-tips {
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
.photo,
|
||||
.video {
|
||||
margin-top: 25px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.btn-area {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.first-btn {
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
form {
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.weui-cell__bd {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
padding: 10px 0;
|
||||
min-height: 30px;
|
||||
}
|
||||
|
||||
.info-container {
|
||||
margin: 12px;
|
||||
text-align: center;
|
||||
}
|
||||
224
xhs-mini-demos/component-case/camera/camera.js
Normal file
224
xhs-mini-demos/component-case/camera/camera.js
Normal file
@@ -0,0 +1,224 @@
|
||||
const vs = `
|
||||
attribute vec3 aPos;
|
||||
attribute vec2 aVertexTextureCoord;
|
||||
varying highp vec2 vTextureCoord;
|
||||
|
||||
void main(void){
|
||||
gl_Position = vec4(aPos, 1);
|
||||
vTextureCoord = aVertexTextureCoord;
|
||||
}
|
||||
`;
|
||||
|
||||
const fs = `
|
||||
varying highp vec2 vTextureCoord;
|
||||
uniform sampler2D uSampler;
|
||||
|
||||
void main(void) {
|
||||
gl_FragColor = texture2D(uSampler, vTextureCoord);
|
||||
}
|
||||
`;
|
||||
|
||||
const vertex = [
|
||||
-1, -1, 0.0,
|
||||
1, -1, 0.0,
|
||||
1, 1, 0.0,
|
||||
-1, 1, 0.0,
|
||||
];
|
||||
|
||||
const vertexIndice = [
|
||||
0, 1, 2,
|
||||
0, 2, 3,
|
||||
];
|
||||
|
||||
const texCoords = [
|
||||
0.0, 0.0,
|
||||
1.0, 0.0,
|
||||
1.0, 1.0,
|
||||
0.0, 1.0,
|
||||
];
|
||||
function createShader(gl, src, type) {
|
||||
const shader = gl.createShader(type);
|
||||
gl.shaderSource(shader, src);
|
||||
gl.compileShader(shader);
|
||||
|
||||
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
||||
console.error(`Error compiling shader: ${gl.getShaderInfoLog(shader)}`);
|
||||
}
|
||||
return shader;
|
||||
}
|
||||
|
||||
const buffers = {};
|
||||
|
||||
function createRenderer(canvas, width, height) {
|
||||
const gl = canvas.getContext('webgl');
|
||||
if (!gl) {
|
||||
console.error('Unable to get webgl context.');
|
||||
return;
|
||||
}
|
||||
|
||||
const info = xhs.getSystemInfoSync();
|
||||
gl.canvas.width = info.pixelRatio * width;
|
||||
gl.canvas.height = info.pixelRatio * height;
|
||||
gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
|
||||
|
||||
const vertexShader = createShader(gl, vs, gl.VERTEX_SHADER);
|
||||
const fragmentShader = createShader(gl, fs, gl.FRAGMENT_SHADER);
|
||||
|
||||
const program = gl.createProgram();
|
||||
gl.attachShader(program, vertexShader);
|
||||
gl.attachShader(program, fragmentShader);
|
||||
gl.linkProgram(program);
|
||||
|
||||
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
||||
console.error('Unable to initialize the shader program.');
|
||||
return;
|
||||
}
|
||||
|
||||
gl.useProgram(program);
|
||||
|
||||
const texture = gl.createTexture();
|
||||
gl.activeTexture(gl.TEXTURE0);
|
||||
gl.bindTexture(gl.TEXTURE_2D, texture);
|
||||
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
||||
gl.bindTexture(gl.TEXTURE_2D, null);
|
||||
|
||||
buffers.vertexBuffer = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, buffers.vertexBuffer);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertex), gl.STATIC_DRAW);
|
||||
|
||||
buffers.vertexIndiceBuffer = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffers.vertexIndiceBuffer);
|
||||
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(vertexIndice), gl.STATIC_DRAW);
|
||||
|
||||
const aVertexPosition = gl.getAttribLocation(program, 'aPos');
|
||||
gl.vertexAttribPointer(aVertexPosition, 3, gl.FLOAT, false, 0, 0);
|
||||
gl.enableVertexAttribArray(aVertexPosition);
|
||||
|
||||
buffers.trianglesTexCoordBuffer = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, buffers.trianglesTexCoordBuffer);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(texCoords), gl.STATIC_DRAW);
|
||||
|
||||
const vertexTexCoordAttribute = gl.getAttribLocation(program, 'aVertexTextureCoord');
|
||||
gl.enableVertexAttribArray(vertexTexCoordAttribute);
|
||||
gl.vertexAttribPointer(vertexTexCoordAttribute, 2, gl.FLOAT, false, 0, 0);
|
||||
|
||||
const samplerUniform = gl.getUniformLocation(program, 'uSampler');
|
||||
gl.uniform1i(samplerUniform, 0);
|
||||
|
||||
return (arrayBuffer, width, height) => {
|
||||
gl.bindTexture(gl.TEXTURE_2D, texture);
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, arrayBuffer);
|
||||
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
|
||||
};
|
||||
}
|
||||
|
||||
Page({
|
||||
onShareAppMessage() {
|
||||
return {
|
||||
title: 'camera',
|
||||
path: 'page/component/pages/camera/camera',
|
||||
};
|
||||
},
|
||||
|
||||
data: {
|
||||
src: '',
|
||||
videoSrc: '',
|
||||
position: 'back',
|
||||
mode: 'scanCode',
|
||||
result: {},
|
||||
frameWidth: 0,
|
||||
frameHeight: 0,
|
||||
width: 288,
|
||||
height: 358,
|
||||
showCanvas: false,
|
||||
},
|
||||
|
||||
onReady() {
|
||||
this.ctx = xhs.createCameraContext();
|
||||
// const selector = xhs.createSelectorQuery();
|
||||
// selector.select('#webgl')
|
||||
// .node(this.init)
|
||||
// .exec()
|
||||
},
|
||||
init(res) {
|
||||
if (this.listener) {
|
||||
this.listener.stop();
|
||||
}
|
||||
const canvas = res.node;
|
||||
const render = createRenderer(canvas, this.data.width, this.data.height);
|
||||
|
||||
// if (!render || typeof render !== 'function') return
|
||||
|
||||
this.listener = this.ctx.onCameraFrame(frame => {
|
||||
render(new Uint8Array(frame.data), frame.width, frame.height);
|
||||
|
||||
const {
|
||||
frameWidth,
|
||||
frameHeight,
|
||||
} = this.data;
|
||||
|
||||
if (frameWidth === frame.width && frameHeight == frame.height) return;
|
||||
this.setData({
|
||||
frameWidth: frame.width,
|
||||
frameHeight: frame.height,
|
||||
|
||||
});
|
||||
});
|
||||
this.listener.start();
|
||||
},
|
||||
takePhoto() {
|
||||
this.ctx.takePhoto({
|
||||
quality: 'high',
|
||||
success: res => {
|
||||
this.setData({
|
||||
src: res.tempImagePath,
|
||||
});
|
||||
},
|
||||
});
|
||||
},
|
||||
startRecord() {
|
||||
this.ctx.startRecord({
|
||||
success: () => {
|
||||
console.log('startRecord');
|
||||
},
|
||||
});
|
||||
},
|
||||
stopRecord() {
|
||||
this.ctx.stopRecord({
|
||||
success: res => {
|
||||
this.setData({
|
||||
src: res.tempThumbPath,
|
||||
videoSrc: res.tempVideoPath,
|
||||
});
|
||||
},
|
||||
});
|
||||
},
|
||||
togglePosition() {
|
||||
this.setData({
|
||||
position: this.data.position === 'front'
|
||||
? 'back' : 'front',
|
||||
});
|
||||
},
|
||||
error(e) {
|
||||
console.log(e.detail);
|
||||
},
|
||||
|
||||
handleShowCanvas() {
|
||||
const that = this;
|
||||
|
||||
this.setData({
|
||||
showCanvas: !this.data.showCanvas,
|
||||
}, () => {
|
||||
if (this.data.showCanvas) {
|
||||
const selector = xhs.createSelectorQuery();
|
||||
selector.select('#webgl')
|
||||
.node(this.init)
|
||||
.exec();
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
3
xhs-mini-demos/component-case/camera/camera.json
Normal file
3
xhs-mini-demos/component-case/camera/camera.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"navigationBarTitleText": "camera"
|
||||
}
|
||||
42
xhs-mini-demos/component-case/camera/camera.xhsml
Normal file
42
xhs-mini-demos/component-case/camera/camera.xhsml
Normal file
@@ -0,0 +1,42 @@
|
||||
<view class="container">
|
||||
<view class="page-body">
|
||||
<view class="page-body-wrapper">
|
||||
<view style="margin-bottom: 10px"> camera 组件 </view>
|
||||
<camera
|
||||
flash="off"
|
||||
device-position="{{position}}"
|
||||
binderror="error"
|
||||
>
|
||||
</camera>
|
||||
<view xhs:if="{{showCanvas}}" class="info-container">
|
||||
<view style="margin: 10px 0">使用实时数据帧在 canvas 组件的展示</view>
|
||||
<view>
|
||||
帧高度:{{ frameHeight }} 帧宽度:{{ frameWidth }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="btn-area first-btn">
|
||||
<button bindtap="handleShowCanvas" type="primary">{{showCanvas ? "关闭实时帧数据模式": "开启实时帧数据模式"}}</button>
|
||||
</view>
|
||||
<view class="btn-area">
|
||||
<button type="primary" bindtap="togglePosition">切换摄像头</button>
|
||||
</view>
|
||||
<view class="btn-area">
|
||||
<button type="primary" bindtap="takePhoto">拍照</button>
|
||||
</view>
|
||||
<view class="btn-area">
|
||||
<button type="primary" bindtap="startRecord">开始录像</button>
|
||||
</view>
|
||||
<view class="btn-area">
|
||||
<button type="primary" bindtap="stopRecord">结束录像</button>
|
||||
</view>
|
||||
<view class="btn-area">
|
||||
<navigator url="/page/component/pages/camera-scan-code/camera-scan-code" hover-class="none">
|
||||
<button type="primary">扫描一维码</button>
|
||||
</navigator>
|
||||
</view>
|
||||
<view class="preview-tips">点击录像或拍照即可在下方预览效果</view>
|
||||
<image xhs:if="{{src}}" mode="widthFix" class="photo" src="{{src}}"></image>
|
||||
<video xhs:if="{{videoSrc}}" class="video" src="{{videoSrc}}"></video>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
Reference in New Issue
Block a user