In my drawing app, Pixel V, I have a color replace tool that lets you restrict where the brush makes a mark to only a chosen color. When the brush was limited to a single pixel width, I just checked the canvas for the color of the pixel at the coordinates of the brush. Once I increased the brush size, this method was no longer practical, and I had to find a new method. The new method I found was to clip the area that had a certain color, thus only allowing the user to draw over the chosen color…


In part 1, we rendered the layers to the DOM, and now we’re going to make it so the layers can be rearranged and interacted with from the DOM.

The important lines here are the ones setting each layer element to draggable: true and associating the actual layer object with the layer element on line 1669 by assigning it to a new property of the layer element. I called it layerObj but you could call it anything.

Now we’re going to use drag events to change the order of the layers.


This won’t be much of a tutorial, but this is a glimpse into my initial attempt to add layers to a drawing app. This is the first time I’ve really thought keeping a state would be useful, so that’s probably the direction I’ll be moving in the future. For now, however, I’ve written some workarounds just to get it started.

Step 1 is to initiate an array of layers and add the default layer:

Most layers will be raster layers, so that’s the only type I’ll focus on for now. …


Try it here.

You may have seen articles about using the box-shadow property in CSS to make pixel art. The process involves creating an element with the width and height of a pixel, and creating a box-shadow for each pixel. It looks something like this:


For my pixel art app, Pixel V, I want to make it easy to use a reference image layered behind or on top of the user’s drawing. For this tutorial, I’m going to go over how to upload files to a website with HTML and JavaScript, as well as how to style that button with CSS.

In HTML, there’s an <input type=”file”/> which we’ll use for getting our file, but it’s not straightforward to style it. So, we’ll create a label for it and style the label instead, while hiding the input element itself.

HTML

<label for="file-upload" class="custom-file-upload btn">…

Try it here.

In my pursuit to render a well-aliased bezier curve for a pixel art tool, I came upon a paper on rasterizing curves by Alois Zingl. The paper covers many types of curves, but I’m just going to focus on quadratic bezier curves. The code in the paper is written in C++, so I translated the code into JavaScript for my purposes. I highly recommend reading the paper, as it explains the concepts very thoroughly.

A bezier curve is defined parametrically, so it can’t be defined with y as a function of x. Instead, you define x and…


Last time we rendered the curve by connecting the pixels with a series of lines, creating a polyline that estimates the bezier curve. That method may work sometimes, but it often produces artifacts when used for pixel art. This time we’re going to try plotting each pixel one after another. However, this is not a simple matter because a bezier curve is a parametric function where the x and y values depend on time (t). Plotting the curve using t results in points that are equally far apart in terms of time, but not in space.

There are two methods…


To give a color picker the expected behavior, there are some tricks to how you set up the interaction between the gradient canvas and the user’s mouse. The main thing is that while the user is holding down click and moving the selector around, the action should still function while the user’s mouse is outside the canvas area.

The key is instead of adding the event listeners to the canvas, add the listeners for mousemove and mouseup to the window.

//canvas listeners
this.target.addEventListener("mousedown", (e) => {
this.handleMouseDown(e);
});
window.addEventListener("mousemove", (e) => {
this.handleMouseMove(e);
});
window.addEventListener("mouseup", (e) => {
this.handleMouseUp(e);
});


In application.rb, add the following line:

config.generators do |g|
g.orm :active_record, primary_key_type: :uuid
end

Create a new migration from the command line:

rails g migration enable_uuid

You should get a file that looks like this:

class EnableUuid < ActiveRecord::Migration[6.0]end

Then add this method inside that migration to enable uuid:

class EnableUuid < ActiveRecord::Migration[6.0]
def change
enable_extension 'uuid-ossp'
enable_extension 'pgcrypto'
end
end

Finally, in your regular migrations, you can set the id type to uuid:

class CreateUsers < ActiveRecord::Migration[6.0]
def change
create_table :users, id: :uuid do |t|
t.string :username
t.timestamps
end
end
end

When you run rails db:migrate, your schema for theUser model should then look like this:

create_table "devices", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
t.string "username"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end

Try it here.

The final product

Last time I went over the basic layout in HTML and CSS. Now I’ll go over creating the gradients and user interaction.

Let’s start by creating a Picker class and assigning all the buttons to associate with. target is the canvas we’ll be using for the main gradient area.

class Picker {
constructor(target, width, height) {
this.target = target;
this.width = width;
this.height = height;
this.target.width = width;
this.target.height = height;
//Get context
this.context =…

Tom Cantwell

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store