Introduction
Oracle JavaScript Extension Toolkit (Oracle JET) empowers developers to build efficient and responsive web applications. It leverages the Virtual DOM (VDOM) architecture, which allows for the creation of VComponents. In this post, I will guide you through the process of creating a VComponent in Oracle JET that includes a drawing pad.
Prerequisites
Ensure that you have Node.js and npm installed on your computer and that you have installed Oracle JET CLI globally. You should also have an Oracle JET application set up and ready for development.
Step 1: Create a new VComponent
Navigate to your Oracle JET application’s root folder and create a new VComponent using the Oracle JET CLI command:
npx @oracle/ojet-cli create component drawingpad-component
Step 2: Define the VComponent
Now, let’s define the structure of our drawing pad VComponent. Open the drawingPad-component.tsx
file and define the component using JSX syntax. Here is the entire code for the drawing pad component. Obviously you can modify to suit your needs, but you can also just copy the code below and paste it :
import { customElement, ExtendGlobalProps } from "ojs/ojvcomponent";
import "ojs/ojbutton";
import { h, Component, ComponentChild } from "preact";
import componentStrings = require("ojL10n!./resources/nls/drawingpad-component-strings");
import "css!./drawingpad-component-styles.css";
type Props = {
footerText?: string;
}
type State = {
drawing: boolean
context?: CanvasRenderingContext2D;
};
/**
*
* @ojmetadata version "1.0.0"
* @ojmetadata displayName "A user friendly, translatable name of the component"
* @ojmetadata description "A translatable high-level description for the component"
*/
@customElement("drawingpad-component")
export class DrawingpadComponent extends Component < ExtendGlobalProps < Props >, State> {
private canvasRef: any = null;
constructor(props: Readonly<{}>) {
super(props);
this.state = { drawing: false };
}
render(props: Props, state: State): ComponentChild {
return (
<div>
<canvas width={500} height={500}
ref={(ref) => (this.canvasRef = ref)}
onMouseDown={this.handleMouseDown}
onMouseUp={this.handleMouseUp}
onMouseMove={this.handleMouseMove}
/>
<oj-button onojAction={this.clearCanvas}>Clear</oj-button>
</div>
); }
componentDidMount() {
this.setState({
context: this.canvasRef.getContext('2d'),
drawing: false
});
}
private clearCanvas = () => {
const context = this.state.context;
if (context) {
context.clearRect(0, 0, this.canvasRef.width, this.canvasRef.height);
}
};
private handleMouseDown = (event: MouseEvent) => {
const rect = this.canvasRef.getBoundingClientRect();
const x = event.clientX - rect.left;
const y = event.clientY - rect.top;
this.setState({ drawing: true });
const context = this.state.context;
if (context) {
context.beginPath();
context.moveTo(x, y);
}
};
private handleMouseUp = (event: MouseEvent) => {
this.setState({ drawing: false });
};
private handleMouseMove = (event: MouseEvent) => {
if (!this.state.drawing) return;
const rect = this.canvasRef.getBoundingClientRect();
this.draw(event.clientX - rect.left, event.clientY - rect.top);
};
draw(x: number, y: number) {
const context = this.state.context;
if (context && this.state.drawing) {
context.lineTo(x, y);
context.stroke();
}
}
}
In this example, we’re creating a canvas and implementing basic drawing functionality. When the mouse button is pressed down, drawing
becomes true
, and when the button is released, drawing
becomes false
. During mouse movement, if drawing
is true
, we draw on the canvas.
Step 3: Style the VComponent
You can add custom styling to your VComponent in the drawingPad.css
file. For instance, you might want to define the size and border of the drawing pad:
canvas {
width: 500px;
height: 500px;
border: 1px solid black;
}
Step 4: Use the VComponent
To use your new DrawingPad VComponent, import it into the desired view, and include it in the render method:
import { h } from "preact";
import { customElement, GlobalProps } from 'ojs/ojvcomponent';
import { DrawingpadComponent } from 'drawingpad-component/loader'
export function Content() {
return (
<div class="oj-web-applayout-max-width oj-web-applayout-content">
<DrawingpadComponent/>
</div>
);
};
In this example, I added the DrawingpadComponent
component to the index.tsx
view. Adjust according to your application structure and the specific view where you want to include the drawing pad.
Now that you’ve created and included the DrawingPad VComponent in your application, you can run and test it.
Click the play button to see a movie of the component in action.
Note regarding HTML5 canvas and 2D:
The 2d
context is a built-in object in HTML5 that provides properties and methods for drawing on the canvas. When you have a canvas element in your HTML, you can access this context using the getContext()
method of the canvas element, like so:
let canvas = document.getElementById('myCanvas');
let ctx = canvas.getContext('2d');
In this example, ctx
is the context object, and it’s through this object that you can draw on the canvas. Here are some of the things you can do with the 2D context:
- Draw rectangles: You can use the
fillRect(x, y, width, height)
method to draw a filled rectangle, or thestrokeRect(x, y, width, height)
method to draw a rectangle outline. - Draw paths: You can use methods like
moveTo(x, y)
,lineTo(x, y)
, andarc(x, y, radius, startAngle, endAngle)
to create paths, and then use thefill()
orstroke()
method to draw the path. - Change colors: You can use the
fillStyle
andstrokeStyle
properties to change the colors used by thefill
andstroke
methods. - Change line styles: You can use the
lineWidth
,lineCap
, andlineJoin
properties to change the style of the lines drawn by thestroke
method. - Draw text: You can use the
fillText(text, x, y)
orstrokeText(text, x, y)
method to draw text. - Draw images: You can use the
drawImage(image, dx, dy)
ordrawImage(image, dx, dy, dWidth, dHeight)
method to draw images. - Save and restore the drawing state: You can use the
save()
andrestore()
methods to save the current drawing state (colors, line styles, etc.) to a stack, and then restore it later. This is useful when you want to make temporary changes to the drawing state without affecting the rest of your drawing code.
In the drawingPad VComponent which was created in this post, we are using the 2D context to draw lines on the canvas when the user moves the mouse while holding down the mouse button. The lineTo(x, y)
method is used to extend the current path to a new point, and the stroke()
method is used to draw the path. You’re also using the beginPath()
method to start a new path each time the user presses the mouse button, and the clearRect(x, y, width, height)
method to clear the canvas when the user clicks the “Clear” button.