kopia lustrzana https://github.com/msurguy/SquiggleCam
Added Section titles
rodzic
35c849dcb9
commit
ec8da1f3cc
325
src/App.vue
325
src/App.vue
|
@ -4,128 +4,156 @@
|
|||
<div class="container">
|
||||
<aside id="panel">
|
||||
<div class="header">
|
||||
<button class="btn btn-primary btn-circle"><i class="fa fa-angle-left"></i></button>
|
||||
<!--<button class="btn btn-primary btn-circle"><i class="fa fa-angle-left"></i></button>-->
|
||||
<h2>SquiggleCam</h2>
|
||||
</div>
|
||||
|
||||
<image-chooser @selected="onInputSelected"></image-chooser>
|
||||
<div class="accordion">
|
||||
<div class="option">
|
||||
<input type="checkbox" checked id="toggle1" class="toggle" />
|
||||
<label class="title" for="toggle1">
|
||||
Image Selection
|
||||
</label>
|
||||
<div class="content">
|
||||
<div class="image-inputs">
|
||||
<image-chooser @selected="onInputSelected"></image-chooser>
|
||||
|
||||
<div class="image-upload" v-if="this.inputType === 'upload'">
|
||||
<croppa v-model="myCroppa" :width="settings.width/2" :height="settings.height/2" :preventWhiteSpace="true" :quality="2"></croppa>
|
||||
<button class="btn btn-primary btn-block" style="display:block;" @click="uploadCroppedImage">Use Image</button>
|
||||
</div>
|
||||
<div class="image-upload" v-if="this.inputType === 'upload'">
|
||||
<croppa v-model="cropper" :width="settings.width/2" :height="settings.height/2" :preventWhiteSpace="false" :quality="2"></croppa>
|
||||
<button class="btn btn-primary btn-block" style="display:block;" @click="uploadCroppedImage">Use Image</button>
|
||||
</div>
|
||||
|
||||
<div class="image-webcam" v-if="this.inputType === 'webcam'">
|
||||
<div class="video-controls">
|
||||
<select v-model="webcam.camera">
|
||||
<option>- Select Device: -</option>
|
||||
<option v-for="device in webcam.devices"
|
||||
:key="device.deviceId"
|
||||
:value="device.deviceId">{{ device.label }}</option>
|
||||
</select>
|
||||
<button v-if="webcam.streaming"
|
||||
type="button"
|
||||
class="btn btn-sm"
|
||||
@click="onStop"><svg width="12" height="12"><rect width="12" height="12" style="fill:rgb(255,0,0)" />
|
||||
</svg></button>
|
||||
<button type="button"
|
||||
class="btn btn-sm"
|
||||
v-if="!webcam.streaming"
|
||||
@click="onStart">Start</button>
|
||||
<div class="image-webcam" v-if="this.inputType === 'webcam'">
|
||||
<div class="video-controls">
|
||||
<select v-model="webcam.camera">
|
||||
<option>- Select Device: -</option>
|
||||
<option v-for="device in webcam.devices"
|
||||
:key="device.deviceId"
|
||||
:value="device.deviceId">{{ device.label }}</option>
|
||||
</select>
|
||||
<button v-if="webcam.streaming"
|
||||
type="button"
|
||||
class="btn btn-sm"
|
||||
@click="onStop"><svg width="12" height="12"><rect width="12" height="12" style="fill:rgb(255,0,0)" />
|
||||
</svg></button>
|
||||
<button type="button"
|
||||
class="btn btn-sm"
|
||||
v-if="!webcam.streaming"
|
||||
@click="onStart">Start</button>
|
||||
</div>
|
||||
|
||||
<webcam ref="webcam"
|
||||
:device-id="webcam.deviceId"
|
||||
:width="settings.width"
|
||||
:height="settings.height"
|
||||
@started="onStarted"
|
||||
@stopped="onStopped"
|
||||
@error="onError"
|
||||
@cameras="onCameras"
|
||||
@camera-change="onCameraChange" />
|
||||
|
||||
<button type="button"
|
||||
class="btn btn-record"
|
||||
v-if="webcam.streaming"
|
||||
@click="onCapture">
|
||||
<svg height="48" width="48" viewBox="0 0 48 48">
|
||||
<circle cx="24" cy="24" r="23" stroke="white" stroke-width="1" fill="#D41616" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<webcam ref="webcam"
|
||||
:device-id="webcam.deviceId"
|
||||
:width="settings.width"
|
||||
:height="settings.height"
|
||||
@started="onStarted"
|
||||
@stopped="onStopped"
|
||||
@error="onError"
|
||||
@cameras="onCameras"
|
||||
@camera-change="onCameraChange" />
|
||||
<div class="option">
|
||||
<input type="checkbox" id="toggle2" class="toggle" />
|
||||
<label class="title" for="toggle2">Paper Settings</label>
|
||||
<div class="content">
|
||||
<div class="slider">
|
||||
<span class="label">
|
||||
Width
|
||||
</span>
|
||||
<input type="range" min="200" max="500" v-model="settings.width">
|
||||
<div class="output">{{ settings.width }}</div>
|
||||
</div>
|
||||
|
||||
<button type="button"
|
||||
class="btn btn-record"
|
||||
v-if="webcam.streaming"
|
||||
@click="onCapture">
|
||||
<svg height="48" width="48" viewBox="0 0 48 48">
|
||||
<circle cx="24" cy="24" r="23" stroke="white" stroke-width="1" fill="#D41616" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div class="slider">
|
||||
<span class="label">
|
||||
Height
|
||||
</span>
|
||||
<input type="range" min="200" max="500" v-model="settings.height">
|
||||
<div class="output">{{ settings.height }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section-title">
|
||||
Squiggle Controls:
|
||||
</div>
|
||||
<div class="option">
|
||||
<input type="checkbox" id="toggle3" class="toggle" />
|
||||
<label class="title" for="toggle3">Image Adjustments</label>
|
||||
<div class="content">
|
||||
<div class="slider">
|
||||
<span class="label">
|
||||
Brightness
|
||||
</span>
|
||||
<input type="range" min="-100" max="100" v-model="settings.brightness">
|
||||
<div class="output">{{ settings.brightness }}</div>
|
||||
</div>
|
||||
|
||||
<div class="slider">
|
||||
<span class="label">
|
||||
Width
|
||||
</span>
|
||||
<input type="range" min="200" max="500" v-model="settings.width">
|
||||
<div class="output">{{ settings.width }}</div>
|
||||
</div>
|
||||
<div class="slider">
|
||||
<span class="label">
|
||||
Contrast
|
||||
</span>
|
||||
<input type="range" min="-100" max="100" v-model="settings.contrast">
|
||||
<div class="output">{{ settings.contrast }}</div>
|
||||
</div>
|
||||
|
||||
<div class="slider">
|
||||
<span class="label">
|
||||
Height
|
||||
</span>
|
||||
<input type="range" min="200" max="500" v-model="settings.height">
|
||||
<div class="output">{{ settings.height }}</div>
|
||||
</div>
|
||||
<div class="slider">
|
||||
<span class="label">
|
||||
Min brightness
|
||||
</span>
|
||||
<input type="range" min="0" max="255" v-model="settings.minBrightness">
|
||||
<div class="output">{{ settings.minBrightness }}</div>
|
||||
</div>
|
||||
|
||||
<div class="slider">
|
||||
<span class="label">
|
||||
Min brightness
|
||||
</span>
|
||||
<input type="range" min="0" max="255" v-model="settings.minBrightness">
|
||||
<div class="output">{{ settings.minBrightness }}</div>
|
||||
</div>
|
||||
<div class="slider">
|
||||
<span class="label">
|
||||
Max brightness
|
||||
</span>
|
||||
<input type="range" min="0" max="255" v-model="settings.maxBrightness">
|
||||
<div class="output">{{ settings.maxBrightness }}</div>
|
||||
</div>
|
||||
|
||||
<div class="slider">
|
||||
<span class="label">
|
||||
Max brightness
|
||||
</span>
|
||||
<input type="range" min="0" max="255" v-model="settings.maxBrightness">
|
||||
<div class="output">{{ settings.maxBrightness }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="slider">
|
||||
<span class="label">
|
||||
Frequency
|
||||
</span>
|
||||
<input type="range" min="5" max="256" v-model="settings.frequency">
|
||||
<div class="output">{{ settings.frequency }}</div>
|
||||
</div>
|
||||
<div class="slider">
|
||||
<span class="label">
|
||||
Line Count
|
||||
</span>
|
||||
<input type="range" min="10" max="200" v-model="settings.lineCount">
|
||||
<div class="output">{{ settings.lineCount }}</div>
|
||||
</div>
|
||||
<div class="slider">
|
||||
<span class="label">
|
||||
Amplitude
|
||||
</span>
|
||||
<input type="range" min="0.1" max="5" step="0.1" v-model="settings.amplitude">
|
||||
<div class="output">{{ settings.amplitude }}</div>
|
||||
</div>
|
||||
<div class="option">
|
||||
<input type="checkbox" id="toggle4" class="toggle" />
|
||||
<label class="title" for="toggle4">Squiggle Settings</label>
|
||||
<div class="content">
|
||||
<div class="slider">
|
||||
<span class="label">
|
||||
Frequency
|
||||
</span>
|
||||
<input type="range" min="5" max="256" v-model="settings.frequency">
|
||||
<div class="output">{{ settings.frequency }}</div>
|
||||
</div>
|
||||
<div class="slider">
|
||||
<span class="label">
|
||||
Line Count
|
||||
</span>
|
||||
<input type="range" min="10" max="200" v-model="settings.lineCount">
|
||||
<div class="output">{{ settings.lineCount }}</div>
|
||||
</div>
|
||||
<div class="slider">
|
||||
<span class="label">
|
||||
Amplitude
|
||||
</span>
|
||||
<input type="range" min="0.1" max="5" step="0.1" v-model="settings.amplitude">
|
||||
<div class="output">{{ settings.amplitude }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="slider">
|
||||
<span class="label">
|
||||
Smoothing
|
||||
</span>
|
||||
<input type="range" min="0" max="0.5" step="0.05" v-model="line.smoothing">
|
||||
<div class="output">{{ line.smoothing}}</div>
|
||||
</div>
|
||||
|
||||
<div class="slider">
|
||||
<span class="label">
|
||||
Flattening
|
||||
</span>
|
||||
<input type="range" min="0" max="1" step="0.01" v-model="line.flattening">
|
||||
<div class="output">{{ line.flattening }}</div>
|
||||
</div>
|
||||
|
||||
<div class="section-title">
|
||||
|
@ -133,7 +161,7 @@
|
|||
</div>
|
||||
<div class="actions">
|
||||
|
||||
<button class="btn" @click="downloadSVG">
|
||||
<button class="btn btn-block" @click="downloadSVG">
|
||||
SVG
|
||||
</button>
|
||||
</div>
|
||||
|
@ -163,18 +191,14 @@
|
|||
},
|
||||
data() {
|
||||
return {
|
||||
myCroppa: {},
|
||||
cropper: {},
|
||||
dataUrl: '',
|
||||
line: {
|
||||
smoothing: 0.25,
|
||||
flattening: 0.5
|
||||
},
|
||||
lines: [],
|
||||
inputType: "upload",
|
||||
settings: {
|
||||
frequency: 150,
|
||||
amplitude: 1,
|
||||
lineCount: 54,
|
||||
lineCount: 50,
|
||||
brightness: 0,
|
||||
contrast: 0,
|
||||
minBrightness: 0,
|
||||
|
@ -216,6 +240,18 @@
|
|||
'settings.amplitude': function(){
|
||||
this.processImage();
|
||||
},
|
||||
'settings.minBrightess': function(){
|
||||
this.processImage();
|
||||
},
|
||||
'settings.maxBrightness': function(){
|
||||
this.processImage();
|
||||
},
|
||||
'settings.brightness': function(){
|
||||
this.processImage();
|
||||
},
|
||||
'settings.contrast': function(){
|
||||
this.processImage();
|
||||
},
|
||||
'canvasData': function(){
|
||||
this.processImage();
|
||||
}
|
||||
|
@ -240,7 +276,7 @@
|
|||
document.body.removeChild(downloadLink);
|
||||
},
|
||||
uploadCroppedImage() {
|
||||
this.myCroppa.generateBlob((blob) => {
|
||||
this.cropper.generateBlob((blob) => {
|
||||
let canvas = document.createElement("canvas");
|
||||
canvas.width = this.settings.width;
|
||||
canvas.height = this.settings.height;
|
||||
|
@ -263,9 +299,15 @@
|
|||
// Gather all necessary data from the main thread
|
||||
let config = data.config;
|
||||
// context.getImageData(0, 0, config.WIDTH, config.HEIGHT);
|
||||
let imagePixels = data.image;
|
||||
let width = parseInt(config.width);
|
||||
let height = parseInt(config.height);
|
||||
const imagePixels = data.image;
|
||||
const width = parseInt(config.width);
|
||||
const height = parseInt(config.height);
|
||||
const contrast = parseInt(config.contrast);
|
||||
const brightness = parseInt(config.brightness);
|
||||
const lineCount = parseInt(config.lineCount);
|
||||
const minBrightness = parseInt(config.minBrightness);
|
||||
const maxBrightness = parseInt(config.maxBrightness);
|
||||
const spacing = parseFloat(config.spacing);
|
||||
|
||||
// Create some defaults for squiggle-point array
|
||||
let squiggleData = [];
|
||||
|
@ -276,8 +318,8 @@
|
|||
let currentLine = []; // create empty array for storing x,y coordinate pairs
|
||||
let currentVerticalPixelIndex = 0;
|
||||
let currentHorizontalPixelIndex = 0;
|
||||
let contrastFactor = (259 * (config.contrast + 255)) / (255 * (259 - config.contrast)); // This was established through experiments
|
||||
let horizontalLineSpacing = Math.floor(height/parseInt(config.lineCount)); // Number of pixels to advance in vertical direction
|
||||
let contrastFactor = (259 * (contrast + 255)) / (255 * (259 - contrast)); // This was established through experiments
|
||||
let horizontalLineSpacing = Math.floor(height / lineCount); // Number of pixels to advance in vertical direction
|
||||
//console.log(horizontalLineSpacing);
|
||||
|
||||
// Iterate line by line (top line to bottom line) in increments of horizontalLineSpacing
|
||||
|
@ -292,32 +334,30 @@
|
|||
|
||||
// Loop through pixels from left to right within the current line, advancing by increments of config.SPACING
|
||||
//console.log(config.spacing, width);
|
||||
for (let x = config.spacing; x < width; x += config.spacing ) {
|
||||
for (let x = spacing; x < width; x += spacing ) {
|
||||
|
||||
currentHorizontalPixelIndex = x + currentVerticalPixelIndex; // Get array position of current pixel
|
||||
|
||||
// When there is contrast adjustment, the calculations of brightness values are a bit different
|
||||
if (config.contrast !== 0) {
|
||||
if (contrast !== 0) {
|
||||
// Determine how bright a pixel is, from 0 to 255 by summing three channels (R,G,B) multiplied by some coefficients
|
||||
b = (0.2125 * ((contrastFactor * (imagePixels.data[4 * currentHorizontalPixelIndex] - 128) + 128 )
|
||||
+ config.brightness)) + (0.7154 * ((contrastFactor * (imagePixels.data[4 * (currentHorizontalPixelIndex + 1)] - 128) + 128)
|
||||
+ config.brightness)) + (0.0721 * ((contrastFactor*(imagePixels.data[4*(currentHorizontalPixelIndex+2)]-128)+128) + config.brightness));
|
||||
+ brightness)) + (0.7154 * ((contrastFactor * (imagePixels.data[4 * (currentHorizontalPixelIndex + 1)] - 128) + 128)
|
||||
+ brightness)) + (0.0721 * ((contrastFactor*(imagePixels.data[4*(currentHorizontalPixelIndex+2)]-128)+128) + brightness));
|
||||
} else {
|
||||
b = (0.2125 * (imagePixels.data[4*currentHorizontalPixelIndex] + config.brightness)) + (0.7154 * (imagePixels.data[4*(currentHorizontalPixelIndex + 1)]+ config.brightness)) + (0.0721 * (imagePixels.data[4*(currentHorizontalPixelIndex + 2)] + config.brightness));
|
||||
b = (0.2125 * (imagePixels.data[4*currentHorizontalPixelIndex] + brightness)) + (0.7154 * (imagePixels.data[4*(currentHorizontalPixelIndex + 1)]+ brightness)) + (0.0721 * (imagePixels.data[4*(currentHorizontalPixelIndex + 2)] + brightness));
|
||||
}
|
||||
|
||||
b = Math.max(config.minBrightness,b); // Set minimum line curvature to value set by the user
|
||||
z = Math.max(config.maxBrightness-b,0); // Set maximum line curvature to value set by the user
|
||||
b = Math.max(minBrightness,b); // Set minimum line curvature to value set by the user
|
||||
z = Math.max(maxBrightness-b,0); // Set maximum line curvature to value set by the user
|
||||
|
||||
// The magic of the script, determines how high / low the squiggle goes
|
||||
r = config.amplitude * z / config.lineCount;
|
||||
r = config.amplitude * z / lineCount;
|
||||
|
||||
a += z / config.frequency;
|
||||
currentLine.push([x,y + Math.sin(a)*r]);
|
||||
//currentLine.push([x,y + 10 * (tmpCounter%2 ? -1 : 1)]);
|
||||
//tmpCounter++;
|
||||
}
|
||||
currentLine.push([config.width, y]);
|
||||
//currentLine.push([config.width, y]);
|
||||
squiggleData.push(currentLine);
|
||||
}
|
||||
|
||||
|
@ -376,27 +416,4 @@
|
|||
|
||||
<style lang="scss">
|
||||
@import './styles/index.scss';
|
||||
|
||||
/*.cropper-header {*/
|
||||
/*background-color: #666;*/
|
||||
/*height: 3rem;*/
|
||||
/*overflow: hidden;*/
|
||||
/*padding-left: 1rem;*/
|
||||
/*padding-right: 1rem;*/
|
||||
/*position: relative;*/
|
||||
/*z-index: 1;*/
|
||||
/*}*/
|
||||
/*@media (min-width: 768px) {*/
|
||||
/*.cropper-header {*/
|
||||
/*padding-left: 1.5rem;*/
|
||||
/*padding-right: 1.5rem;*/
|
||||
/*}*/
|
||||
/*}*/
|
||||
.title {
|
||||
color: #fff;
|
||||
display: block;
|
||||
float: left;
|
||||
font-size: 1.125rem;
|
||||
line-height: 3rem;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -137,9 +137,6 @@
|
|||
}
|
||||
// Emit video start/live event
|
||||
this.$refs.video.onloadedmetadata = () => {
|
||||
// this.width = 500;
|
||||
// this.height = 500;
|
||||
|
||||
this.$emit("video-live", stream);
|
||||
};
|
||||
|
||||
|
@ -191,7 +188,6 @@
|
|||
* load the Camera passed as index!
|
||||
*/
|
||||
loadCamera(device) {
|
||||
console.log('loading camera, width', this.width);
|
||||
navigator.mediaDevices
|
||||
.getUserMedia({
|
||||
video: {
|
||||
|
@ -210,15 +206,12 @@
|
|||
return this.getCanvas().toDataURL(this.screenshotFormat);
|
||||
},
|
||||
getCanvasRaw() {
|
||||
//const { ctx, canvas } = this;
|
||||
return this.ctx.getImageData(0,0,this.canvas.width, this.canvas.height);
|
||||
},
|
||||
getCanvas() {
|
||||
let video = this.$refs.video;
|
||||
if (!this.ctx) {
|
||||
let canvas = document.createElement("canvas");
|
||||
//console.log(video.width);
|
||||
//console.log(video.height);
|
||||
canvas.height = video.height;
|
||||
canvas.width = video.width;
|
||||
this.canvas = canvas;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" :view-box.camel="viewbox" :width="width" :height="height">
|
||||
<g>
|
||||
<svg-chart-line :d="line" :o="options" v-for="(line, index) in lines" :key="index"></svg-chart-line>
|
||||
<svg-chart-line :d="line" v-for="(line, index) in lines" :key="index"></svg-chart-line>
|
||||
</g>
|
||||
</svg>
|
||||
</template>
|
||||
|
|
|
@ -3,48 +3,21 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import * as lib from "../lib";
|
||||
|
||||
export default {
|
||||
name: "svgChartLine",
|
||||
props: ["d", "o"],
|
||||
props: ["d"],
|
||||
computed: {
|
||||
pathD() {
|
||||
return this.pointsPositions.reduce((acc, e, i, a) => i === 0
|
||||
? `M ${e[0]},${e[1]}`
|
||||
: `${acc} ${this.bezierCommand(e, i, a)}`
|
||||
, "");
|
||||
},
|
||||
pointsPositions() {
|
||||
return this.d.values
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
line(pointA, pointB) {
|
||||
const lengthX = pointB[0] - pointA[0];
|
||||
const lengthY = pointB[1] - pointA[1];
|
||||
return {
|
||||
length: Math.sqrt(Math.pow(lengthX, 2) + Math.pow(lengthY, 2)),
|
||||
angle: Math.atan2(lengthY, lengthX)
|
||||
};
|
||||
},
|
||||
controlPoint(current, previous, next, reverse) {
|
||||
const p = previous || current;
|
||||
const n = next || current;
|
||||
const o = this.line(p, n);
|
||||
// work in progress…
|
||||
const flat = lib.map(Math.cos(o.angle) * this.o.flattening, 0, 1, 1, 0)
|
||||
const angle = o.angle * flat + (reverse ? Math.PI : 0);
|
||||
const length = o.length * this.o.smoothing;
|
||||
const x = Math.round((current[0] + Math.cos(angle) * length) * 100) / 100 ;
|
||||
const y = Math.round((current[1] + Math.sin(angle) * length) * 100) / 100 ;
|
||||
return [x, y];
|
||||
},
|
||||
bezierCommand(point, i, a) {
|
||||
const cps = this.controlPoint(a[i - 1], a[i - 2], point);
|
||||
const cpe = this.controlPoint(point, a[i - 1], a[i + 1], true);
|
||||
//const close = i === a.length - 1 ? " z" : "";
|
||||
return `C ${cps[0]},${cps[1]} ${cpe[0]},${cpe[1]} ${Math.round(point[0] * 100) / 100},${Math.round(point[1]*100)/100}`;
|
||||
let path = "";
|
||||
|
||||
this.d.values.forEach((point, index) => {
|
||||
if (index === 0) {
|
||||
path += `M ${point[0]},${point[1]}`;
|
||||
} else {
|
||||
path += `L${Math.round(point[0] * 100) / 100},${Math.round(point[1]*100)/100}`
|
||||
}
|
||||
});
|
||||
return path;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -201,7 +201,8 @@ input[type="range"]::-webkit-slider-runnable-track {
|
|||
width: 100%;
|
||||
height: 5px;
|
||||
cursor: pointer;
|
||||
background-image: linear-gradient(-270deg, #fad961 0%, #f76b1c 100%);
|
||||
background-color: #717171;
|
||||
// background-image: linear-gradient(-270deg, #fad961 0%, #f76b1c 100%);
|
||||
//box-shadow: 0px 0px 0px #6f2200, 0px 0px 0px #892a00;
|
||||
//background: #f76b1c;
|
||||
//border-radius: 5px;
|
||||
|
@ -218,18 +219,20 @@ input[type="range"]::-webkit-slider-thumb {
|
|||
-webkit-appearance: none;
|
||||
margin-top: -7.5px;
|
||||
}
|
||||
input[type="range"]:focus::-webkit-slider-runnable-track {
|
||||
input[type="range"]:hover::-webkit-slider-runnable-track {
|
||||
//background: #f8813e;
|
||||
background-image: linear-gradient(-270deg, #fad961 0%, #f76b1c 100%);
|
||||
}
|
||||
input[type="range"]:focus::-webkit-slider-runnable-track {
|
||||
background-image: linear-gradient(-270deg, #fad961 0%, #f76b1c 100%);
|
||||
}
|
||||
input[type="range"]::-moz-range-track {
|
||||
width: 100%;
|
||||
height: 5px;
|
||||
cursor: pointer;
|
||||
//box-shadow: 0px 0px 0px #6f2200, 0px 0px 0px #892a00;
|
||||
background: #f76b1c;
|
||||
background-image: linear-gradient(-270deg, #fad961 0%, #f76b1c 100%);
|
||||
border-radius: 5px;
|
||||
//border: 1px solid #18d501;
|
||||
}
|
||||
input[type="range"]::-moz-range-thumb {
|
||||
box-shadow: 1.6px 1.6px 2.5px #cccccc, 0px 0px 1.6px #d9d9d9;
|
||||
|
@ -250,15 +253,15 @@ input[type="range"]::-ms-track {
|
|||
}
|
||||
input[type="range"]::-ms-fill-lower {
|
||||
background: #e75908;
|
||||
border: 0px solid #18d501;
|
||||
border: none;
|
||||
border-radius: 2px;
|
||||
box-shadow: 0px 0px 0px #6f2200, 0px 0px 0px #892a00;
|
||||
//box-shadow: 0px 0px 0px #6f2200, 0px 0px 0px #892a00;
|
||||
}
|
||||
input[type="range"]::-ms-fill-upper {
|
||||
background: #f76b1c;
|
||||
border: 0px solid #18d501;
|
||||
border: none;
|
||||
border-radius: 2px;
|
||||
box-shadow: 0px 0px 0px #6f2200, 0px 0px 0px #892a00;
|
||||
//box-shadow: 0px 0px 0px #6f2200, 0px 0px 0px #892a00;
|
||||
}
|
||||
input[type="range"]::-ms-thumb {
|
||||
box-shadow: 1.6px 1.6px 2.5px #cccccc, 0px 0px 1.6px #d9d9d9;
|
||||
|
@ -268,7 +271,6 @@ input[type="range"]::-ms-thumb {
|
|||
border-radius: 10px;
|
||||
background: #298bff;
|
||||
cursor: pointer;
|
||||
height: 5px;
|
||||
}
|
||||
input[type="range"]:focus::-ms-fill-lower {
|
||||
background: #f76b1c;
|
||||
|
@ -277,14 +279,14 @@ input[type="range"]:focus::-ms-fill-upper {
|
|||
background: #f8813e;
|
||||
}
|
||||
|
||||
.image-inputs {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
// & > * {
|
||||
// //flex: 1;
|
||||
//}
|
||||
|
||||
padding-bottom: 20px;
|
||||
.btn {
|
||||
background-color: $btn-bg;
|
||||
color: $btn-text-color;
|
||||
|
@ -292,34 +294,40 @@ input[type="range"]:focus::-ms-fill-upper {
|
|||
|
||||
&:hover {
|
||||
background-color: #6b6b6b;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.btn-block{
|
||||
width: 100%;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.section-title {
|
||||
margin-top: 25px;
|
||||
margin-top: 15px;
|
||||
margin-bottom: 15px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.slider {
|
||||
position: relative;
|
||||
height: 65px;
|
||||
display: flex;
|
||||
margin-bottom: 7px;
|
||||
|
||||
.label {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
top: 8px;
|
||||
line-height: 18px;
|
||||
right: 0px;
|
||||
font-family: Monaco;
|
||||
right: 0;
|
||||
font-family: Monaco, monospace;
|
||||
font-size: 12px;
|
||||
color: #d2d2d2;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
input[type="range"] {
|
||||
margin-top: 18px;
|
||||
margin-top: 35px;
|
||||
}
|
||||
|
||||
.output {
|
||||
|
@ -333,7 +341,7 @@ input[type="range"]:focus::-ms-fill-upper {
|
|||
font-family: monaco, Consolas, Lucida Console, monospace;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.header {
|
||||
|
@ -351,6 +359,7 @@ input[type="range"]:focus::-ms-fill-upper {
|
|||
|
||||
.image-webcam {
|
||||
position: relative;
|
||||
margin-bottom: 30px;
|
||||
|
||||
.btn-record {
|
||||
position: absolute;
|
||||
|
@ -362,3 +371,56 @@ input[type="range"]:focus::-ms-fill-upper {
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
.toggle {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.option {
|
||||
position: relative;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.title {
|
||||
text-transform: uppercase;
|
||||
text-align: left;
|
||||
background-color: $btn-bg;
|
||||
color: $btn-text-color;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.title,
|
||||
.content {
|
||||
backface-visibility: hidden;
|
||||
transform: translateZ(0);
|
||||
transition: all 0.3s;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.title:before {
|
||||
content: '';
|
||||
border-style: solid;
|
||||
border-width: 2px 2px 0 0;
|
||||
position: absolute;
|
||||
right: 15px;
|
||||
top: 15px;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
transform: rotate(45deg);
|
||||
transform-origin: 75% 20%;
|
||||
transition: transform 0.3s;
|
||||
}
|
||||
|
||||
.content {
|
||||
max-height: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.toggle:checked {
|
||||
& + .title + .content {
|
||||
max-height: 500px;
|
||||
}
|
||||
& + .title:before {
|
||||
transform: rotate(135deg) !important;
|
||||
}
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue