Files
xhs-examples/xhs-mini-demos/component-case/camera/camera.js
2025-09-14 00:21:54 +08:00

225 lines
5.6 KiB
JavaScript

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();
}
});
},
});