feat 大头贴
@ -0,0 +1,60 @@
|
|||||||
|
@charset "utf-8";
|
||||||
|
|
||||||
|
:root {
|
||||||
|
font-size: 1vw;
|
||||||
|
--c-d-1: #000;
|
||||||
|
--c-l-1: #FFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
body,html {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
border: 0;
|
||||||
|
height: 100vh;
|
||||||
|
width: 100vw;
|
||||||
|
background-color: var(--c-d-1);
|
||||||
|
color: var(--c-l-1);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-root {
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vw;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.p-root>*{
|
||||||
|
border: none;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
position:absolute;
|
||||||
|
top:0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
.p-root>div{
|
||||||
|
line-height: 100vw;
|
||||||
|
text-align: center;
|
||||||
|
color: rgba(255,255,255,.3);
|
||||||
|
text-shadow: 0 0 1vw rgba(0,0,0,.5);
|
||||||
|
font-size: 15vw;
|
||||||
|
font-weight: 900;
|
||||||
|
}
|
||||||
|
.p-root>div>div {
|
||||||
|
float: left;
|
||||||
|
width: 50vw;
|
||||||
|
}
|
||||||
|
.p-imgs {
|
||||||
|
width: 100vw;
|
||||||
|
height: calc(50vh - 50vw);
|
||||||
|
display: flex;
|
||||||
|
overflow: visible;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-imgs>img {
|
||||||
|
width: calc(50vh - 52vw);
|
||||||
|
height: calc(50vh - 52vw);
|
||||||
|
margin: 1vw;
|
||||||
|
background-color: var(--c-l-1);
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 538 KiB |
|
After Width: | Height: | Size: 362 KiB |
|
After Width: | Height: | Size: 6.2 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 188 KiB |
|
After Width: | Height: | Size: 147 KiB |
|
After Width: | Height: | Size: 96 KiB |
|
After Width: | Height: | Size: 99 KiB |
|
After Width: | Height: | Size: 166 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 111 KiB |
|
After Width: | Height: | Size: 48 KiB |
|
After Width: | Height: | Size: 114 KiB |
|
After Width: | Height: | Size: 122 KiB |
|
After Width: | Height: | Size: 167 KiB |
|
After Width: | Height: | Size: 132 KiB |
|
After Width: | Height: | Size: 88 KiB |
|
After Width: | Height: | Size: 73 KiB |
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 60 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 164 KiB |
@ -0,0 +1 @@
|
|||||||
|
image.png
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>大头贴</title>
|
||||||
|
<link rel="stylesheet" href="css/index.css">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div class="p-root">
|
||||||
|
<video muted autoplay width="1200" height="1200"></video>
|
||||||
|
<canvas width="1200" height="1200"></canvas>
|
||||||
|
<img src="imgs/01.png">
|
||||||
|
<div>拍照</div>
|
||||||
|
<div>
|
||||||
|
<div>确定</div>
|
||||||
|
<div>取消</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!--下面放图片模板-->
|
||||||
|
<div class="p-imgs">
|
||||||
|
</div>
|
||||||
|
<!--下面放拍好的照片-->
|
||||||
|
<div class="p-imgs">
|
||||||
|
</div>
|
||||||
|
<script type="module" src="js/index.js"></script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
@ -0,0 +1,134 @@
|
|||||||
|
let root = document.querySelector(".p-root");
|
||||||
|
let imgs = document.querySelectorAll(".p-imgs");
|
||||||
|
let video = root.children[0];
|
||||||
|
let canvas = root.children[1];
|
||||||
|
let img = root.children[2];
|
||||||
|
let btnTack = root.children[3];
|
||||||
|
let btns = root.children[4];
|
||||||
|
let btnConfirm = btns.children[0];
|
||||||
|
let btnCancel = btns.children[1];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理点击选择模板图片
|
||||||
|
*/
|
||||||
|
imgs[0].addEventListener("click", (e) => {
|
||||||
|
if (e.target instanceof HTMLImageElement) {
|
||||||
|
img.src = e.target.src;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成模板图片
|
||||||
|
*/
|
||||||
|
for (let i = 1; i <= 24; i++) {
|
||||||
|
let img = new Image();
|
||||||
|
img.onerror = () => {
|
||||||
|
img.src = "imgs/01.png";
|
||||||
|
}
|
||||||
|
img.src = "imgs/" + i.toString().padStart(2, "0") + ".png";
|
||||||
|
imgs[0].appendChild(img);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理图片的左右移动
|
||||||
|
*/
|
||||||
|
imgs.forEach(item => {
|
||||||
|
let x = 0;
|
||||||
|
let x1 = -1;
|
||||||
|
console.info(item.scrollWidth, item.clientWidth);
|
||||||
|
item.addEventListener("touchmove", (e) => {//绑定触摸移动事件
|
||||||
|
if (x1 > -1) {
|
||||||
|
x += e.changedTouches[0].screenX - x1;
|
||||||
|
}
|
||||||
|
x1 = e.changedTouches[0].screenX;
|
||||||
|
item.style.left = x + "px";
|
||||||
|
});
|
||||||
|
item.addEventListener("touchend", (e) => {//绑定触摸移动事件结束
|
||||||
|
x1 = -1;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取视频流
|
||||||
|
*/
|
||||||
|
btns.hidden = true;//确定,取消不可见
|
||||||
|
navigator.mediaDevices.getUserMedia({
|
||||||
|
audio: false,
|
||||||
|
video: {
|
||||||
|
facingMode: "environment",//前置:user,后置:environment
|
||||||
|
width: { min: 800, ideal: 1080, max: 2000 },
|
||||||
|
height: { min: 800, ideal: 1080, max: 2000 }
|
||||||
|
}
|
||||||
|
// width:800,
|
||||||
|
// height:800
|
||||||
|
|
||||||
|
|
||||||
|
// }).catch(e=>{
|
||||||
|
// console.error(e);
|
||||||
|
// return navigator.mediaDevices.getUserMedia({
|
||||||
|
// audio:false,
|
||||||
|
// video:{
|
||||||
|
// facingMode: "environment",//前置:user,后置:environment
|
||||||
|
// // width: {min:100,ideal: 200,max:2000},
|
||||||
|
// // height: {min:100,ideal: 200,max:2000 }
|
||||||
|
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
}).then((stream) => {
|
||||||
|
console.info(stream);
|
||||||
|
console.info(stream.getTracks()[0]);
|
||||||
|
console.info(stream.getTracks()[0].getConstraints());
|
||||||
|
console.info(stream.getTracks()[0].getSettings());
|
||||||
|
console.info(stream.getTracks()[0].getCapabilities());
|
||||||
|
console.info(stream.getTracks()[0].applyConstraints());
|
||||||
|
console.info(stream.getVideoTracks());
|
||||||
|
// video.onloadedmetadata = function (e) {
|
||||||
|
// console.info(e);
|
||||||
|
// };
|
||||||
|
video.srcObject = stream;
|
||||||
|
}).catch(e => {
|
||||||
|
console.error(e);
|
||||||
|
alert("摄像设备不可用");
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理拍照
|
||||||
|
*/
|
||||||
|
btnTack.addEventListener("click", () => {
|
||||||
|
canvas.getContext('2d').drawImage(video, 0, 0, 1200, 1200);
|
||||||
|
btnTack.hidden = true;
|
||||||
|
btns.hidden = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理取消
|
||||||
|
*/
|
||||||
|
btnCancel.addEventListener("click", () => {
|
||||||
|
canvas.getContext('2d').clearRect(0, 0, 1200, 1200);
|
||||||
|
btnTack.hidden = false;
|
||||||
|
btns.hidden = true;
|
||||||
|
});
|
||||||
|
/**
|
||||||
|
* 处理确定
|
||||||
|
*/
|
||||||
|
btnConfirm.addEventListener("click", () => {
|
||||||
|
canvas.getContext('2d').drawImage(img, 0, 0, 1200, 1200);
|
||||||
|
let item = new Image();
|
||||||
|
item.src = canvas.toDataURL("image/png");
|
||||||
|
imgs[1].appendChild(item);
|
||||||
|
canvas.getContext('2d').clearRect(0, 0, 1200, 1200);
|
||||||
|
btnTack.hidden = false;
|
||||||
|
btns.hidden = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理点击照片事件
|
||||||
|
*/
|
||||||
|
imgs[1].addEventListener("click", (e) => {
|
||||||
|
if (e.target instanceof HTMLImageElement) {
|
||||||
|
let a = document.createElement("a");
|
||||||
|
a.href = e.target.src;
|
||||||
|
a.download = "大头贴-" + new Date().getTime() + ".png";
|
||||||
|
a.click();
|
||||||
|
}
|
||||||
|
});
|
||||||
@ -0,0 +1,93 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>实验01.抓取摄像头图片到画布</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div class="temp">
|
||||||
|
<div title="摄像头">
|
||||||
|
<video class="p-camera" muted autoplay></video>
|
||||||
|
<button class="p-button">拍照</button>
|
||||||
|
</div>
|
||||||
|
<div title="画布">
|
||||||
|
<canvas class="p-canvas"></canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<style>
|
||||||
|
:root {
|
||||||
|
font-size: 1vw;
|
||||||
|
--c-d-1: #000;
|
||||||
|
--c-l-1: #FFF;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
padding: 1rem;
|
||||||
|
background-color: var(--c-l-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.temp {
|
||||||
|
display: grid;
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.temp>* {
|
||||||
|
border: var(--c-d-1) .1rem solid;
|
||||||
|
min-height: 10rem;
|
||||||
|
position: relative;
|
||||||
|
padding: .7rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.temp>*[title]::before {
|
||||||
|
content: attr(title);
|
||||||
|
position: absolute;
|
||||||
|
font-size: 1rem;
|
||||||
|
line-height: 1;
|
||||||
|
background-color: var(--c-l-1);
|
||||||
|
top: -.7rem;
|
||||||
|
left: 1rem;
|
||||||
|
}
|
||||||
|
.p-camera,.p-canvas {
|
||||||
|
background-color: var(--c-d-1);
|
||||||
|
width: 100%;
|
||||||
|
height: 40vh;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script type="module">
|
||||||
|
let root = document.body;
|
||||||
|
let camera = root.querySelector(".p-camera");
|
||||||
|
let button = root.querySelector(".p-button");
|
||||||
|
let canvas = root.querySelector(".p-canvas");
|
||||||
|
console.debug(camera,button,canvas);
|
||||||
|
console.debug(camera.clientWidth,camera.clientHeight);
|
||||||
|
canvas.setAttribute("width",camera.clientWidth);
|
||||||
|
canvas.setAttribute("height",camera.clientHeight);
|
||||||
|
camera.setAttribute("width",camera.clientWidth);
|
||||||
|
camera.setAttribute("height",camera.clientHeight);
|
||||||
|
|
||||||
|
navigator.mediaDevices.getUserMedia({
|
||||||
|
audio:false,
|
||||||
|
video:{
|
||||||
|
facingMode: "environment",//前置:user,后置:environment
|
||||||
|
width: {ideal: camera.clientWidth},
|
||||||
|
height: {ideal: camera.clientHeight }
|
||||||
|
|
||||||
|
}
|
||||||
|
}).then((stream)=>{
|
||||||
|
camera.srcObject=stream;
|
||||||
|
}).catch(e=>{
|
||||||
|
console.debug(e.message);
|
||||||
|
console.error(e);
|
||||||
|
});
|
||||||
|
button.addEventListener("click",()=>{
|
||||||
|
canvas.getContext('2d').drawImage(camera, 0, 0, camera.clientWidth,camera.clientHeight);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
@ -0,0 +1,63 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>实验02.使用画布合成多张图片</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<canvas></canvas>
|
||||||
|
<canvas></canvas>
|
||||||
|
<canvas></canvas>
|
||||||
|
<button>保存画布图片</button>
|
||||||
|
<style>
|
||||||
|
canvas {
|
||||||
|
border: 3px solid #FFF;
|
||||||
|
border-radius: 2px;
|
||||||
|
box-shadow: 0 0 2px #666;
|
||||||
|
width: 400px;
|
||||||
|
height: 400px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script type="module">
|
||||||
|
let cs = document.querySelectorAll("canvas");
|
||||||
|
for(let c of cs){
|
||||||
|
c.width=2000;
|
||||||
|
c.height=2000;
|
||||||
|
}
|
||||||
|
console.debug(cs);
|
||||||
|
let c0 = cs[0].getContext("2d");
|
||||||
|
let c1 = cs[1].getContext("2d");
|
||||||
|
let c2 = cs[2].getContext("2d");
|
||||||
|
console.debug(c1);
|
||||||
|
let loadImage = function(src){
|
||||||
|
return new Promise((resolve,reject)=>{
|
||||||
|
let img = new Image();
|
||||||
|
img.onload=()=>{
|
||||||
|
resolve(img);
|
||||||
|
};
|
||||||
|
img.onerror=reject;
|
||||||
|
img.style.display="none";
|
||||||
|
img.src=src;
|
||||||
|
document.body.appendChild(img);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
loadImage("imgs/01.png").then((img)=>{
|
||||||
|
c0.drawImage(img,0,0,2000,2000);
|
||||||
|
c2.drawImage(img,0,0,2000,2000);
|
||||||
|
return loadImage("imgs/02.png");
|
||||||
|
}).then((img)=>{
|
||||||
|
c1.drawImage(img,0,0,2000,2000);
|
||||||
|
c2.drawImage(img,0,0,2000,2000);
|
||||||
|
});
|
||||||
|
document.querySelector("button").onclick=()=>{
|
||||||
|
let a = document.createElement("a");
|
||||||
|
a.href = cs[2].toDataURL("image/png");
|
||||||
|
a.download="大头贴-"+new Date().getTime()+".png";
|
||||||
|
a.click();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||