style: added documentation with JSDoc and html comments
This commit is contained in:
parent
e33747e7b3
commit
13944b526f
10
index.html
10
index.html
|
@ -13,11 +13,16 @@
|
||||||
<title>Imagine - Image Editor</title>
|
<title>Imagine - Image Editor</title>
|
||||||
</head>
|
</head>
|
||||||
<body class="import-active">
|
<body class="import-active">
|
||||||
|
<!--
|
||||||
|
body classes allow for switching between the three views:
|
||||||
|
import-active, camera-active and editor-active
|
||||||
|
-->
|
||||||
<div class="navbar columns is-mobile is-fixed-top">
|
<div class="navbar columns is-mobile is-fixed-top">
|
||||||
<div class="column" id="viewport">
|
<div class="column" id="viewport">
|
||||||
<div class="hero is-fullheight">
|
<div class="hero is-fullheight">
|
||||||
<div class="hero-body">
|
<div class="hero-body">
|
||||||
<div class="container" >
|
<div class="container" >
|
||||||
|
<!-- viewport that contains canvas/video/import buttons -->
|
||||||
<canvas id="myCanvas" class="is-visible-editor" width="300" height="300"></canvas>
|
<canvas id="myCanvas" class="is-visible-editor" width="300" height="300"></canvas>
|
||||||
<video id="video" class="is-visible-camera" width="300" height="300"></video>
|
<video id="video" class="is-visible-camera" width="300" height="300"></video>
|
||||||
<div class="container has-text-centered mb-6 is-visible-import">
|
<div class="container has-text-centered mb-6 is-visible-import">
|
||||||
|
@ -43,7 +48,8 @@
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div><br>
|
</div>
|
||||||
|
<!-- buttons inside of the viewport -->
|
||||||
<a id="settings-button" href="#settings" class="button is-hidden-desktop is-visible-editor">
|
<a id="settings-button" href="#settings" class="button is-hidden-desktop is-visible-editor">
|
||||||
<i class="fa-solid fa-sliders mr-2"></i> Settings
|
<i class="fa-solid fa-sliders mr-2"></i> Settings
|
||||||
</a>
|
</a>
|
||||||
|
@ -56,6 +62,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- settings menu for desktop use -->
|
||||||
<div class="column is-narrow has-background-black-ter is-hidden-mobile is-hidden-tablet-only is-visible-editor">
|
<div class="column is-narrow has-background-black-ter is-hidden-mobile is-hidden-tablet-only is-visible-editor">
|
||||||
<aside class="menu mr-3">
|
<aside class="menu mr-3">
|
||||||
<h1 class="title">Imagine</h1>
|
<h1 class="title">Imagine</h1>
|
||||||
|
@ -214,6 +221,7 @@
|
||||||
</aside>
|
</aside>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- settings menu for mobile use -->
|
||||||
<div id="settings" class="notification is-fullwidth is-hidden-desktop is-visible-editor">
|
<div id="settings" class="notification is-fullwidth is-hidden-desktop is-visible-editor">
|
||||||
<!-- #settings is an anhor to scroll to when clicked on the settings-button -->
|
<!-- #settings is an anhor to scroll to when clicked on the settings-button -->
|
||||||
<!-- #top is an anchor provided by the browser to go to the top of the page -->
|
<!-- #top is an anchor provided by the browser to go to the top of the page -->
|
||||||
|
|
61
main.js
61
main.js
|
@ -1,6 +1,10 @@
|
||||||
let canvas;
|
let canvas;
|
||||||
let video;
|
let video;
|
||||||
let ctx;
|
let ctx;
|
||||||
|
/*
|
||||||
|
* theses settings correspond to a css-filter. you can specify an optional
|
||||||
|
* filter attribute to modify the value from the input element.
|
||||||
|
*/
|
||||||
let settings = {
|
let settings = {
|
||||||
"brightness": {},
|
"brightness": {},
|
||||||
"saturate": {},
|
"saturate": {},
|
||||||
|
@ -111,6 +115,11 @@ document.addEventListener("DOMContentLoaded", function() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset all inputs of a setting back to the default value
|
||||||
|
*
|
||||||
|
* @param {string} setting - key of the settings object to reset
|
||||||
|
*/
|
||||||
function reset_all(setting) {
|
function reset_all(setting) {
|
||||||
console.log("reseting " + setting);
|
console.log("reseting " + setting);
|
||||||
for (let element of settings[setting].elements) {
|
for (let element of settings[setting].elements) {
|
||||||
|
@ -119,6 +128,10 @@ function reset_all(setting) {
|
||||||
draw(true);
|
draw(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request camera access and on succhess, show camera feed on video-element and
|
||||||
|
* switch to camera-active view
|
||||||
|
*/
|
||||||
function use_camera() {
|
function use_camera() {
|
||||||
navigator.mediaDevices
|
navigator.mediaDevices
|
||||||
.getUserMedia({ video: true, audio: false })
|
.getUserMedia({ video: true, audio: false })
|
||||||
|
@ -132,6 +145,10 @@ function use_camera() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Take a still frame of the video-element showing the camera-feed and load it
|
||||||
|
* to the img to be rendered by canvas and switch to editor-active view
|
||||||
|
*/
|
||||||
function take_picture() {
|
function take_picture() {
|
||||||
canvas.width = video.width;
|
canvas.width = video.width;
|
||||||
canvas.height = video.height;
|
canvas.height = video.height;
|
||||||
|
@ -142,6 +159,10 @@ function take_picture() {
|
||||||
document.body.className = "editor-active";
|
document.body.className = "editor-active";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load selected file by input element to img to be rendered by canvas and
|
||||||
|
* switch to editor-active view
|
||||||
|
*/
|
||||||
function upload_image() {
|
function upload_image() {
|
||||||
document.body.className = "editor-active";
|
document.body.className = "editor-active";
|
||||||
|
|
||||||
|
@ -151,7 +172,14 @@ function upload_image() {
|
||||||
img.onload = () => draw(true);
|
img.onload = () => draw(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/File_drag_and_drop
|
/**
|
||||||
|
* Get file that is dropped into the website and load it to img to be rendered
|
||||||
|
* by canvas and switch to editor-active view.
|
||||||
|
*
|
||||||
|
* @param {DragEvent} ev -supplier by event listener
|
||||||
|
*
|
||||||
|
* https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/File_drag_and_drop
|
||||||
|
*/
|
||||||
function drop_handler(ev) {
|
function drop_handler(ev) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
let file;
|
let file;
|
||||||
|
@ -170,6 +198,12 @@ function drop_handler(ev) {
|
||||||
img.onload = () => draw(true);
|
img.onload = () => draw(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a download of the edited image in full resolution by creating a link
|
||||||
|
* and virtually clicking it.
|
||||||
|
*
|
||||||
|
* @param {PointerEvent} event - supplied by event listener
|
||||||
|
*/
|
||||||
function save_image(event) {
|
function save_image(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
draw(false);
|
draw(false);
|
||||||
|
@ -182,6 +216,11 @@ function save_image(event) {
|
||||||
link.click();
|
link.click();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uses the navigator.share API to share the edited image in full reslution.
|
||||||
|
*
|
||||||
|
* @param {PointerEvent} event - supplied by event listener
|
||||||
|
*/
|
||||||
function share_image(event) {
|
function share_image(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
if (!navigator.share) {
|
if (!navigator.share) {
|
||||||
|
@ -201,6 +240,11 @@ function share_image(event) {
|
||||||
}, 'image/png');
|
}, 'image/png');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set all inputs of a setting to the value of the input that changed it.
|
||||||
|
*
|
||||||
|
* @param {Event} event - supplied by event listener
|
||||||
|
*/
|
||||||
function settings_apply(event) {
|
function settings_apply(event) {
|
||||||
const changed_setting = event.target.id;
|
const changed_setting = event.target.id;
|
||||||
const new_value = event.target.value;
|
const new_value = event.target.value;
|
||||||
|
@ -214,7 +258,13 @@ function settings_apply(event) {
|
||||||
draw(true);
|
draw(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://www.shadertoy.com/view/ldSXWK
|
/**
|
||||||
|
* Render a lensflare shader for every pixel on the canvas.
|
||||||
|
*
|
||||||
|
* @param {number} pos_x - x position of the lensflare in the range [-0.5,0.5]
|
||||||
|
* @param {number} pos_y - y position of the lensflare in the range [-0.5,0.5]
|
||||||
|
* https://www.shadertoy.com/view/ldSXWK
|
||||||
|
*/
|
||||||
function lensflare(pos_x, pos_y) {
|
function lensflare(pos_x, pos_y) {
|
||||||
const imgdata = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
const imgdata = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
||||||
const pixel_count = imgdata.data.length / 4;
|
const pixel_count = imgdata.data.length / 4;
|
||||||
|
@ -276,6 +326,13 @@ function lensflare(pos_x, pos_y) {
|
||||||
ctx.putImageData(imgdata, 0, 0);
|
ctx.putImageData(imgdata, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Amply filters and lensflare to the optionally scaled image, to only
|
||||||
|
* calculate on pixels the user can see.
|
||||||
|
*
|
||||||
|
* @param {bool} viewport_scale - render image scaled to viewport or in full
|
||||||
|
* resolution
|
||||||
|
*/
|
||||||
function draw(viewport_scale) {
|
function draw(viewport_scale) {
|
||||||
const filter = Object.entries(settings)
|
const filter = Object.entries(settings)
|
||||||
.map(([setting, { elements, filter }]) => `${setting}(${filter(elements[0].value)})`)
|
.map(([setting, { elements, filter }]) => `${setting}(${filter(elements[0].value)})`)
|
||||||
|
|
Loading…
Reference in a new issue