Unsuccessful Execution of Plain Javascript within Angular CLI Component

I am in the process of developing a website using Angular CLI. I am attempting to implement something similar to this example :

https://codepen.io/chrisdoble/pen/WQLLVp

Is there a way to write plain JavaScript in component.ts.

Here is my JavaScript :

    var image = document.getElementById('hero-bg');
    var imageCanvas = document.createElement('canvas');
    var imageCanvasContext = imageCanvas.getContext('2d');
    var lineCanvas = document.createElement('canvas');
    var lineCanvasContext = lineCanvas.getContext('2d');
    var pointLifetime = 1000;
    var points = [];
    var newImage = document.getElementById('hero')

    if (image.complete) {
        start();
    } else {
        image.onload = start;
    }

    function start() {
        document.addEventListener('mousemove', onMouseMove);
        window.addEventListener('resize', resizeCanvases);
        newImage.appendChild(imageCanvas);
        resizeCanvases();
        tick();
    }

    function onMouseMove(event) {
        points.push({
            time: Date.now(),
            x: event.clientX,
            y: event.clientY
        });
    }

    function resizeCanvases() {
        imageCanvas.width = lineCanvas.width = window.innerWidth;
        imageCanvas.height = lineCanvas.height = window.innerHeight;
    }

    function tick() {
        // Remove old points
        points = points.filter(function(point) {
            var age = Date.now() - point.time;
            return age < pointLifetime;

        });

        drawLineCanvas();
        drawImageCanvas();
        requestAnimationFrame(tick);
    }
    function drawLineCanvas() {
        var minimumLineWidth = 25;
        var maximumLineWidth = 100;
        var lineWidthRange = maximumLineWidth - minimumLineWidth;
        var maximumSpeed = 50;

        lineCanvasContext.clearRect(0, 0, lineCanvas.width, lineCanvas.height);
        lineCanvasContext.lineCap = 'round';
        lineCanvasContext.shadowBlur = 30;
        lineCanvasContext.shadowColor = '#000';

        for (var i = 1; i < points.length; i++) {
            var point = points[i];
            var previousPoint = points[i - 1];

            // Change line width based on speed
            var distance = getDistanceBetween(point, previousPoint);
            var speed = Math.max(0, Math.min(maximumSpeed, distance));
            var percentageLineWidth = (maximumSpeed - speed) / maximumSpeed;
            lineCanvasContext.lineWidth = minimumLineWidth + percentageLineWidth * lineWidthRange;

            // Fade points as they age
            var age = Date.now() - point.time;
            var opacity = (pointLifetime - age) / pointLifetime;
            lineCanvasContext.strokeStyle = 'rgba(0, 0, 0, ' + opacity + ')';

            lineCanvasContext.beginPath();
            lineCanvasContext.moveTo(previousPoint.x, previousPoint.y);
            lineCanvasContext.lineTo(point.x, point.y);
            lineCanvasContext.stroke();
        }
    }

    function getDistanceBetween(a, b) {
        return Math.sqrt(Math.pow(a.x - b.x, 2) + Math.pow(a.y - b.y, 2));
    }

    function drawImageCanvas() {
        // Emulate background-size: cover
        var width = imageCanvas.width;
        var height = imageCanvas.width / image.naturalWidth * image.naturalHeight;

        if (height < imageCanvas.height) {
            width = imageCanvas.height / image.naturalHeight * image.naturalWidth;
            height = imageCanvas.height;
        }

        imageCanvasContext.clearRect(0, 0, imageCanvas.width, imageCanvas.height);
        imageCanvasContext.globalCompositeOperation = 'source-over';
        imageCanvasContext.drawImage(image, 0, 0, width, height);
        imageCanvasContext.globalCompositeOperation = 'destination-in';
        imageCanvasContext.drawImage(lineCanvas, 0, 0);
    }

And here is my Component

import { Component } from '@angular/core';
import * as $ from 'jquery';

@Component({
selector: 'app-hero',
templateUrl: './hero.component.html',
styleUrls: ['./hero.component.scss']
})
export class HeroComponent {


}

The Error I encountered is as follows :

  • message: 'Property 'complete' does not exist on type 'HTMLElement'.'
  • message: 'Property 'naturalWidth' does not exist on type 'HTMLElement'.'
  • message: 'Property 'naturalHeight' does not exist on type 'HTMLElement'.'
  • message: 'Argument of type 'HTMLElement' is not assignable to parameter of type 'HTMLCanvasElement | HTMLImageElement | HTMLVideoElement | ImageBitmap'. Type 'HTMLElement' is not assignable to type 'ImageBitmap'. Property 'width' is missing in type 'HTMLElement'.'

Everything functions properly when the code is inserted directly into the Index.html file, however, I prefer to integrate it within my component.

Please assist me in figuring out how to implement this plain JavaScript in my component.ts. Or perhaps if there are any TypeScript experts present, kindly refactor the code for me. Hehehe Thank you very much, everyone.

Answer №2

Absolutely, it is possible to do so.

However, it is important to handle the following:

ElementRef : https://angular.io/api/core/ElementRef

Renderer : https://angular.io/api/core/Renderer

or Renderer 2.

In Typescript, you will need to specify the type of element as HTMLElement.

For instance:

svg: SVGElement = ...

In your specific scenario, ensure to declare that your element is of type: HTMLImageElement.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Encountering a data property error while trying to render ejs using axios

I am encountering an error message "TypeError: Cannot read property 'data' of undefined" when trying to display results.ejs using data from an API. Can someone help me identify what's incorrect with the rendering code? Thank you. index.js: ...

An unexpected error arose while executing the ng serve command

I recently upgraded my machine and installed the latest node, Angular Cli, npm, and other necessary packages for my app. After cloning the repo, I used npm-check-updates to update all local packages to their current versions. To resolve peer dependency iss ...

run a function once ngFor has completed rendering the data

I'm attempting to run a function every time my ngFor finishes loading data from the API. However, the callback only works on the initial load of the ngFor. How can I make sure that the callback is executed whenever my ngFor data changes? I found a ...

Is there a way to include a different component without it automatically displaying within a div element?

Is there a way to make the Torrent component render without directly binding it to a DOM element? I am facing an issue with my Torrent Table Component as I want it to be populated with Torrent Components based on API data, but it's not rendering beca ...

Find the exact length of a string in an HTML5 canvas

In my HTML5 canvas project, I am overlaying text on an image (creating a meme generator). My goal is to determine the perfect font size so that the text covers the entire width of the canvas. Is there a JavaScript solution to calculate the ideal font size ...

Placing a footer at the bottom of a webpage with the help of Bootstrap

Looking for some assistance with creating a page using bootstrap 4.5.2, as it's new territory for me. I'm trying to automatically position a footer at the bottom of the page without resorting to absolute positioning. I attempted to use mt-auto o ...

Is it possible for variables in a component.ts file to be automatically updated without the need for an updateData()/ngOnit method to be called again within the same component.ts file

I recently started working with Angular and came across a logic issue while implementing a function using a service class in my component class. Here is the code snippet that I encountered: Link to Stackblitz app.module.ts @NgModule({ declarations: [ ...

What is the best way to design a versatile instanceof function that returns the object if it matches the specified type?

I am currently working on developing a function with this structure: function isInstance<T>(s: T): T | boolean { return (s instanceof T) && s; } The purpose of this function is to return the value as that type if it is an instance, otherwise it re ...

ReCaptcha: connecting to the TextBox's OnKeyDown event using script

I've been figuring out how to integrate ReCaptcha, ASP.NET, and Gaia Ajax. It was a bit of a challenge to use the ReCaptcha AJAX APIs with Gaia to fetch the data from the recaptcha_response_field text box in an AJAX postback through a patch. This was ...

Add a JavaScript file into a PHP document

I've been searching for a solution in various forums, but the main answer I found doesn't seem to work for me. As someone new to Web development, I'm attempting to create a simple JavaScript program that takes a JSON string of products and ...

Jquery and Magento Prototype causing conflicts

I am attempting to implement the Foundation 5 Reveal modal on a Magento product page. To do this, I have included jQuery and foundation.js in the footer and initialized Foundation from footer.phtml <script src="js/vendor/jquery.js"></script> ...

Using Jasmine to Jest: Mocking Nested function calls

I am currently working on testing my TypeScript functions with Jasmine: //AB.ts export async function A() { } export async function B() { A(); } My goal is to unit test function B by mocking out function A to see if it is called. Here is the code I h ...

Exploring Angular 2+: Asynchronous Testing with setTimeout

I have a question regarding my testing process. I am using Angular 6, karma, and jasmine. Here is the test I have written: it(`my test`, async(() => { console.log('### start test'); fixture.detectChanges(); // calling a method wi ...

I'm facing a challenge with displaying data on a dynamically created table using VueJS

I'm having an issue with dynamically generating a table using VueJS. The problem arises when creating the <th> elements. In order to set them up, I have a Vue component that is called by the addRow function. This component uses templates with v ...

Associate a click event to a dropdown menu element to trigger on selection

My issue involves having multiple select elements. When one of them is changed, I am trying to bind a click event only to its next element with the .btn class. Below is the code snippet illustrating my problem: <div class="whole"> <ul> ...

"Selecting an object in Three.js after it has been deleted

Implementing object picking in code is a popular technique: function Picking(event) { var raycaster = new THREE.Raycaster(); event.preventDefault(); mouse.x = (event.clientX / renderer.domElement.clientWidth) * 2 - 1; mouse.y = -(event.clientY / renderer. ...

I encountered an issue in ReactJS where I received a TypeError stating that props.history.listen is not a function

Why is this showing up? I'm using ReactJS and can't figure out what's going wrong. Here is my history.js: import { createBrowserHistory } from 'history' export default createBrowserHistory In my App.js: import React from 'r ...

Using interfaces from a different file becomes challenging as they cannot access any external dependencies when imported

Encountering an issue with interface importing. When the interface contains non-import dependencies and is located in separate files like: /src/app/something/something.interface.ts interface ISomething { a: String[]; } I am able to utilize it in ano ...

Is there a more efficient approach to configuring properties in AngularJS while maintaining a binding?

When trying to set a property in a service equal to data returned from a network call, the conventional method goes like this: //SERVICE// thisService.property = data; //SERVICE// The corresponding controller code usually looks something like this: //CO ...

PHP: Utilizing $_SESSION variables for automatic form filling across various PHP pages

I've spent an hour searching for a solution to the problem below, but I haven't been able to find one that fits my specific issue. However, I have some ideas that I'll share after outlining the problem. Problem: In an html form within a ph ...