diff --git a/color_function/index.html b/color_function/index.html index a76f35b..dc58d64 100644 --- a/color_function/index.html +++ b/color_function/index.html @@ -33,8 +33,8 @@ - + diff --git a/color_function/library/classdefinitions.js b/color_function/library/classdefinitions.js index ba501fd..f0e2bda 100644 --- a/color_function/library/classdefinitions.js +++ b/color_function/library/classdefinitions.js @@ -1,12 +1,3 @@ -//IMPROVEMENT AREAS - -//5 It might be more efficient to use a single method to handle the hue, saturation, and lightness calculations, instead of having separate methods for each in the Square class. - -//6 The class Square_matrix is using the Math.abs function to keep the saturation and lightness values between 0 and 100. An alternative approach would be to use the modulo operator % to ensure that the value is within the desired range, which would be more efficient. - -//7 The class Square_matrix is using the replace method to replace X and Y in the expressions, it could use a more powerful and efficient way like using a template string to replace the X and Y values. - - class Square { constructor(ctx, xpos, ypos, hue, saturation, lightness, square_size) { this.xpos = xpos; @@ -16,7 +7,6 @@ class Square { this.lightness = lightness; this.square_size = square_size; this.ctx = ctx; - // this.draw(); } draw() { @@ -36,17 +26,15 @@ class Square { } hue_changed(expression, x, y) { - - this.hue = math.evaluate(`${expression}`.replace(/X/g, x).replace(/Y/g, y)); + this.hue = Function( `return ${expression.replace(/X/g, x).replace(/Y/g, y)}` )(); this.draw(); } saturation_changed(expression, x, y) { - this.saturation = Math.abs( ((100 + math.evaluate(`${expression}`.replace(/X/g, x).replace(/Y/g, y))) % 200) - 100 ); - + this.saturation = Math.abs( ((100 + Function(`return ${expression.replace(/X/g, x).replace(/Y/g, y)}`)()) % 200) - 100 ); this.draw(); } lightness_changed(expression, x, y) { - this.lightness = Math.abs( ((100 + math.evaluate(`${expression}`.replace(/X/g, x).replace(/Y/g, y))) % 200) - 100 ); + this.lightness = Math.abs( ((100 + Function(`return ${expression.replace(/X/g, x).replace(/Y/g, y)}`)()) % 200) - 100 ); this.draw(); } } @@ -88,12 +76,12 @@ class Square_matrix { } for (let y = start_y, runs = length; y <= runs; y++) { - let color_x = x * this.pixel_ratio; - let color_y = y * this.pixel_ratio; + const color_x = x * this.pixel_ratio; + const color_y = y * this.pixel_ratio; - const hue = math.evaluate(`${this.hue_expression}`.replace(/X/g, color_x).replace(/Y/g, color_y)); - const saturation = Math.abs( ((100 + math.evaluate(`${this.saturation_expression}`.replace(/X/g, color_x).replace(/Y/g, color_y))) % 200) - 100 ); - const lightness = Math.abs( ((100 + math.evaluate(`${this.lightness_expression}`.replace(/X/g, color_x).replace(/Y/g, color_y))) % 200) - 100 ); + const hue = Function( `return ${this.hue_expression .replace(/X/g, color_x) .replace(/Y/g, color_y)}` )(); + const saturation = Math.abs( ((100 + Function( `return + ${this.saturation_expression .replace(/X/g, color_x) .replace(/Y/g, color_y)}` )()) % 200) - 100 ); + const lightness = Math.abs( ((100 + Function( `return + ${this.lightness_expression .replace(/X/g, color_x) .replace(/Y/g, color_y)}` )()) % 200) - 100 ); this.square_matrix[x][y] = new Square( this.ctx, @@ -115,12 +103,12 @@ class Square_matrix { // row for (let x = start_y, runs = length; x <= runs; x++) { for (let y = start_x, runs = width; y <= runs; y++) { - let color_x = x * this.pixel_ratio; - let color_y = y * this.pixel_ratio; + const color_x = x * this.pixel_ratio; + const color_y = y * this.pixel_ratio; - const hue = math.evaluate(`${this.hue_expression}`.replace(/X/g, color_x).replace(/Y/g, color_y)); - const saturation = Math.abs( ((100 + math.evaluate(`${this.saturation_expression}`.replace(/X/g, color_x).replace(/Y/g, color_y))) % 200) - 100 ); - const lightness = Math.abs( ((100 + math.evaluate(`${this.lightness_expression}`.replace(/X/g, color_x).replace(/Y/g, color_y))) % 200) - 100 ); + const hue = Function( `return ${this.hue_expression .replace(/X/g, color_x) .replace(/Y/g, color_y)}` )(); + const saturation = Math.abs( ((100 + Function( `return + ${this.saturation_expression .replace(/X/g, color_x) .replace(/Y/g, color_y)}` )()) % 200) - 100 ); + const lightness = Math.abs( ((100 + Function( `return + ${this.lightness_expression .replace(/X/g, color_x) .replace(/Y/g, color_y)}` )()) % 200) - 100 ); this.square_matrix[x][y] = new Square( this.ctx, @@ -160,7 +148,7 @@ class Square_matrix { } else if (method === "lightness") { - this.lightness = component; + this.lightness_expression = component; var class_method = Square.prototype.lightness_changed; } @@ -179,7 +167,7 @@ class Square_matrix { this.size_lower = size_lower; this.size_upper = size_upper; - //old_size_bipartite means its either the old size_lower or old size_upper + // old_size_bipartite means its either the old size_lower or old size_upper switch (true) { //size_upper changed @@ -201,16 +189,14 @@ class Square_matrix { } zoom(cursor_start_x, cursor_end_x, cursor_start_y, cursor_end_y) { + const zoom_area = largest_drawable_square( cursor_start_x, cursor_end_x, cursor_start_y, cursor_end_y ); const canvas_current_x = cursor_start_x + zoom_area.width; const canvas_current_y = cursor_start_y + zoom_area.height; - const canvas_start_x = 0; - const canvas_start_y = 0; - //zooms if a perfect square is makeable, guiding box fits the canvas - if ( canvas_start_x < canvas_current_x && canvas_current_x < this.canvas.width && canvas_start_y < canvas_current_y && canvas_current_y < this.canvas.height ) { + if ( 0 < canvas_current_x && canvas_current_x < this.canvas.width && 0 < canvas_current_y && canvas_current_y < this.canvas.height ) { //start is the smallest value, while end is the largest, opposite for y value because it is distance from top of canvas const start_x = Math.min( ~~(cursor_start_x / this.absolute_width) + this.distance_left_x, ~~((cursor_start_x + zoom_area.width) / this.absolute_width) + this.distance_left_x ); diff --git a/color_function/library/functions.js b/color_function/library/functions.js index e176419..f220197 100644 --- a/color_function/library/functions.js +++ b/color_function/library/functions.js @@ -1,26 +1,28 @@ //Returns angle between two vectors, unit can be "deg" or radians function v2a(vector1, vector2, unit) { - vector1_length = Math.sqrt(vector1[0] ** 2 + vector1[1] ** 2); - vector2_length = Math.sqrt(vector2[0] ** 2 + vector2[1] ** 2); - vector_product = vector1[0] * vector2[0] + vector1[1] * vector2[1]; + const vector1_length = Math.sqrt(vector1[0] ** 2 + vector1[1] ** 2); + const vector2_length = Math.sqrt(vector2[0] ** 2 + vector2[1] ** 2); + if (vector1_length == 0 || vector2_length == 0) { + return NaN; + } + const vector_product = vector1[0] * vector2[0] + vector1[1] * vector2[1]; //angle as degrees if (unit == "deg") { - var angle = (Math.acos(vector_product / (vector1_length * vector2_length)) * 180) / Math.PI; + const angle = (Math.acos(vector_product / (vector1_length * vector2_length)) * 180) / Math.PI; return angle; } //angle as radians else { - var angle = Math.acos(vector_product / (vector1_length * vector2_length)); + const angle = Math.acos(vector_product / (vector1_length * vector2_length)); return angle; } } function largest_drawable_square(cursor_start_x, cursor_end_x, cursor_start_y, cursor_end_y) { - let height = 0; //Positive values down, negative values up. - let width = 0; //positive values to the right, negative to the left. + let width = 0; //positive values to the right, negative to the left. //checks which quadrant mouse is in relation to the initially clicked point (think unit circle quadrants or whatever) let quadrant = "top_right"; @@ -36,8 +38,8 @@ function largest_drawable_square(cursor_start_x, cursor_end_x, cursor_start_y, c } } - const square_width = cursor_end_x - cursor_start_x - const square_height = cursor_end_y - cursor_start_y + const square_width = cursor_end_x - cursor_start_x; + const square_height = cursor_end_y - cursor_start_y; //finds the cursor x or y position which would give the greatest width or height (both?) //current mouse position is in top right or bottom left quadrant (quadrant top_right or bottom_left) if (quadrant == "top_right" || quadrant == "bottom_left") { @@ -61,21 +63,22 @@ function largest_drawable_square(cursor_start_x, cursor_end_x, cursor_start_y, c height = width; } } - return {cursor_start_x, cursor_end_x, cursor_start_y, cursor_end_y, width, height, }; + return { cursor_start_x, cursor_end_x, cursor_start_y, cursor_end_y, width, height, }; } -function draw_square(canvas_info, background_img, cursor_start_x, cursor_end_x,cursor_start_y, cursor_end_y) { - let canvas = canvas_info; +function draw_square(canvas_info, background_img, cursor_start_x, cursor_end_x, cursor_start_y, cursor_end_y) { + const canvas = canvas_info; const ctx = canvas.getContext("2d", { alpha: false }); - let current_square = largest_drawable_square(cursor_start_x, cursor_end_x, cursor_start_y, cursor_end_y); + const current_square = largest_drawable_square(cursor_start_x, cursor_end_x, cursor_start_y, cursor_end_y); - let parameter_x = cursor_start_x + ~~current_square.width; - let parameter_y = cursor_start_y + ~~current_square.height; + const parameter_x = cursor_start_x + ~~current_square.width; + const parameter_y = cursor_start_y + ~~current_square.height; + //Draws the guiding box if it fits the canvas - if ( (parameter_x < canvas.width && parameter_x > 0) && (parameter_y < canvas.height && parameter_y > 0) ) { + if ( (0 < parameter_x && parameter_x < canvas.width) && (0 < parameter_y && parameter_y < canvas.height ) ) { ctx.drawImage(background_img, 0, 0, canvas.width, canvas.height); ctx.beginPath(); - ctx.rect(cursor_start_x, cursor_start_y, current_square.width, current_square.height); + ctx.rect( cursor_start_x, cursor_start_y, current_square.width, current_square.height ); ctx.stroke(); } } @@ -83,4 +86,4 @@ function draw_square(canvas_info, background_img, cursor_start_x, cursor_end_x,c function get_cursor_position(canvas, event) { //finds the absolute coordinates clicked, given as distence from top left. return [event.offsetX, event.offsetY]; -} \ No newline at end of file +} diff --git a/color_function/script.js b/color_function/script.js index e1587ba..3187b2b 100644 --- a/color_function/script.js +++ b/color_function/script.js @@ -2,71 +2,66 @@ const c = console.log.bind(console); -const get_hue_expression = document.getElementById("hue_expression"); -const get_saturation_expression = document.getElementById("saturation_expression"); -const get_lightness_expression = document.getElementById("lightness_expression"); -const get_size_lower = document.getElementById("size_lower"); -const get_size_upper = document.getElementById("size_upper"); -const get_pixel_ratio = document.getElementById("pixel_ratio"); -const get_upscale_button = document.getElementById("upscale"); +const get_hue_expression = document.querySelector("#hue_expression"); +const get_saturation_expression = document.querySelector("#saturation_expression"); +const get_lightness_expression = document.querySelector("#lightness_expression"); +const get_size_lower = document.querySelector("#size_lower"); +const get_size_upper = document.querySelector("#size_upper"); +const get_pixel_ratio = document.querySelector("#pixel_ratio"); +const get_upscale_button = document.querySelector("#upscale"); get_hue_expression.addEventListener("change", function () { - hue_expression = get_hue_expression.value; + // hue_expression = get_hue_expression.value; ctx.clearRect(0, 0, canvas.width, canvas.height) - matrix_squares.class_method_loop("hue", hue_expression); + matrix_squares.class_method_loop("hue", get_hue_expression.value); update_images(canvas) }); get_saturation_expression.addEventListener("change", function () { - saturation_expression = get_saturation_expression.value; + // saturation_expression = get_saturation_expression.value; ctx.clearRect(0, 0, canvas.width, canvas.height) - matrix_squares.class_method_loop("saturation", saturation_expression); + matrix_squares.class_method_loop("saturation", get_saturation_expression.value); update_images(canvas) }); get_lightness_expression.addEventListener("change", function () { - lightness_expression = get_lightness_expression.value; + // lightness_expression = get_lightness_expression.value; ctx.clearRect(0, 0, canvas.width, canvas.height) - matrix_squares.class_method_loop("lightness", lightness_expression); + matrix_squares.class_method_loop("lightness", get_lightness_expression.value); update_images(canvas) }); get_pixel_ratio.addEventListener("change", function () { pixel_ratio = +get_pixel_ratio.value; - size_upper = ~~(+get_size_upper.value / pixel_ratio); - size_lower = ~~(+get_size_lower.value / pixel_ratio); + size_upper = Math.floor(+get_size_upper.value / pixel_ratio); + size_lower = Math.floor(+get_size_lower.value / pixel_ratio); distance_left_x_zooming = size_lower distance_top_y_zooming = size_lower + matrix_squares.create_squares(size_lower, size_lower, size_upper, size_upper, pixel_ratio) update_images(canvas) }); get_size_lower.addEventListener("change", function () { let old_size = size_lower - size_lower = ~~(+get_size_lower.value / pixel_ratio); - - + size_lower = Math.floor(+get_size_lower.value / pixel_ratio); const absolute_width = canvas.width / (size_upper - size_lower + index_zero); var distance_from_top_left = (absolute_width) * (old_size - size_lower) var image_size = ((absolute_width) * (size_upper - old_size + index_zero )) ctx.drawImage(resizing_img, distance_from_top_left, distance_from_top_left, image_size, image_size); - - - + matrix_squares.change_size(size_lower, size_upper, old_size, 'lower'); update_images(canvas) }); get_size_upper.addEventListener("change", function () { let old_size = size_upper - size_upper = ~~(+get_size_upper.value / pixel_ratio); + size_upper = Math.floor(+get_size_upper.value / pixel_ratio); const absolute_width = canvas.width / (size_upper - size_lower + index_zero); var image_size = ((absolute_width) * (old_size - size_lower + index_zero)) ctx.drawImage(resizing_img, 0, 0, image_size, image_size); - - matrix_squares.change_size(size_lower, size_upper, old_size, 'higher'); update_images(canvas) }); @@ -78,7 +73,7 @@ get_upscale_button.addEventListener("click", function () { //-----------------------Canvas----------------------------- -let canvas = document.getElementById("canvas"); +let canvas = document.querySelector("#canvas"); const ctx = canvas.getContext("2d", { alpha: false }); //Check class for these settings! @@ -87,16 +82,15 @@ const ctx = canvas.getContext("2d", { alpha: false }); //----------------Creation of pixels-------------------------------- -const index_zero = 1 let matrix_pixels = []; let size_lower = +get_size_lower.value; let size_upper = +get_size_upper.value; -let size = size_upper - size_lower + index_zero; -var pixel_ratio = parseFloat(get_pixel_ratio.value); +var pixel_ratio= +(get_pixel_ratio.value); +const index_zero = 1 -let hue_expression = get_hue_expression.value; -let saturation_expression = get_saturation_expression.value; -let lightness_expression = get_lightness_expression.value; +// let hue_expression = get_hue_expression.value; +// let saturation_expression = get_saturation_expression.value; +// let lightness_expression = get_lightness_expression.value; //-------------------------------ZOOMING-------------------- @@ -104,7 +98,6 @@ let initial_cursor_position = [] let current_cursor_position = [] let mouse_is_down = false - // Event listener for all cursor on canvas events function handle_canvas_event_zoom(event) { switch (event.type) { @@ -170,9 +163,10 @@ var distance_top_y_zooming = size_lower window.onload = winInit; function winInit() { // ctx.filter = "hue-rotate(200deg)" //INTERESTING! - matrix_squares = new Square_matrix(canvas, hue_expression, saturation_expression, lightness_expression) + matrix_squares = new Square_matrix(canvas, get_hue_expression.value, get_saturation_expression.value, get_lightness_expression.value) matrix_squares.create_squares(size_lower, size_lower, size_upper, size_upper, pixel_ratio) update_images(canvas) + } //\\\\\\\\\\\\\\\\\\\\FUNCTIONS\\\\\\\\\\\\\\\\\\\\\\\ @@ -201,20 +195,19 @@ function update_images(canvas){ // } // runspeed = get_runspeed.value; // animId = setInterval(draw_pixels, 1000 / runspeed); -//TODO: the draw_pixels function must be made again if i want make a changing variable that changes every second or whatever // } // } //------------------END-------------------- //!HUGE? TODO: use webworkers, ask chat gpt-3 for help, not viable? passing information between webworker and main script removes class -//TODO: Research complex plotting or whatever, make an option to change to using complex numbers? +//TODO: !Research complex plotting or whatever, make an option to change to using complex numbers? -//TODO: Create a settings button where settings can be changed/toggled? -//TODO:! Add a button for the option to redraw the black background, creates very interesting patterns when the size of the pixels are < 1 -//TODO: Make an option to turn on the sawtooth pattern for hue too? and create lower and upper limit, this.hue = Math.abs(( (100 + Function("return " + hue_expression)()) % 200) - 100) +//TODO: create a settings button where settings can be changed/toggled? +//TODO:! add a button for the option to redraw the black background, creates very interesting patterns when the size of the pixels are < 1 +//TODO: make an option to turn on the sawtooth pattern for hue too? and create lower and upper limit, this.hue = Math.abs(( (100 + Function("return " + hue_expression)()) % 200) - 100) //!TODO: Create a option to toggle between clicking a button to run script and running script when a variable is changed. -//!TODO: Performance mode and fast mode, ise ctx.drawimage method for fast and redraw every pixel every time for fast mode. +//!TODO: quality mode and fast mode, ise ctx.drawimage method for fast and redraw every pixel every time for fast mode. //TODO: save settings in localstorage //TODO: Create option to make a variable that changes every second f.eks. goes from 1 to 10 then 10 to 1, call it n and then n can be used in the color chooser @@ -239,4 +232,4 @@ function update_images(canvas){ //* WONTFIX Minor fix in the new_pixels function, it creates the corner piece twice //* make it possible to zoom in on inzoomed image. //* made zooming more general -//* made functions into methods +//* made functions into methods \ No newline at end of file