"Using a triangular background shape in JavaScript instead of a traditional circular

I want to add a unique effect to my site inspired by the AnimatedHeaderBackgrounds demo available at this link.

My twist on this effect involves using upward-moving triangles instead of circles. I've explored various resources, including Stack Overflow, but haven't quite achieved the desired result.

  (function() {

    var width, height, largeHeader, canvas, ctx, triangles, target, animateHeader = true;
    var colors = ['72,35,68', '43,81,102', '66,152,103', '250,178,67', '224,33,48'];

    // Main
    initHeader();
    addListeners();

    function initHeader() {
        width = window.innerWidth;
        height = window.innerHeight;
        target = {x: 0, y: height};

        largeHeader = document.getElementById('large-header');
        largeHeader.style.height = height+'px';

        canvas = document.getElementById('demo-canvas');
        canvas.width = width;
        canvas.height = height;
        ctx = canvas.getContext('2d');

        // create particles
        triangles = [];
        for(var x = 0; x < width*0.5; x++) {
            var c = new Triangle();
            triangles.push(c);
        }
        animate();
    }

    // Event handling
    function addListeners() {
        window.addEventListener('scroll', scrollCheck);
        window.addEventListener('resize', resize);
    }

    function scrollCheck() {
        if(document.body.scrollTop > height) animateHeader = false;
        else animateHeader = true;
    }

    function resize() {
        width = window.innerWidth;
        height = window.innerHeight;
        largeHeader.style.height = height+'px';
        canvas.width = width;
        canvas.height = height;
    }

    function animate() {
        if(animateHeader) {
            ctx.clearRect(0,0,width,height);
            for(var i in triangles) {
                triangles[i].draw();
            }
        }
        requestAnimationFrame(animate);
    }

    // Canvas manipulation
    function Triangle() {
        var _this = this;

        // constructor
        (function() {
            _this.coords = [{},{},{}];
            _this.pos = {};
            init();
        })();

        function init() {
            _this.pos.x = Math.random()*width;
            _this.pos.y = height+Math.random()*100;
            _this.alpha = 0.1+Math.random()*0.3;
            _this.scale = 0.1+Math.random()*0.3;
            _this.velocity = Math.random();
        }

        this.draw = function() {
            if(_this.alpha >= 0.005){
               _this.alpha -= 0.005;
            } else {
                _this.alpha = 0;
            }
            ctx.beginPath();
            ctx.moveTo(_this.coords[0].x+_this.pos.x, _this.coords[0].y+_this.pos.y);
            ctx.lineTo(_this.coords[1].x+_this.pos.x, _this.coords[1].y+_this.pos.y);
            ctx.lineTo(_this.coords[2].x+_this.pos.x, _this.coords[2].y+_this.pos.y);
            ctx.closePath();
            ctx.fillStyle = 'rgba('+_this.color+','+ _this.alpha+')';
            ctx.fill();
        };

        this.init = init;
    }

})();

For more insights, I referred to a relevant Stack Overflow thread on creating equilateral triangles within a canvas, accessible here. Here's the complete code snippet:

(function() {

    var width, height, largeHeader, canvas, ctx, circles, target, animateHeader = true;

    // Main
    initHeader();
    addListeners();

    function initHeader() {
        width = window.innerWidth;
        height = window.innerHeight;
        target = {x: 0, y: height};

        largeHeader = document.getElementById('large-header');
        largeHeader.style.height = height+'px';

        canvas = document.getElementById('demo-canvas');
        canvas.width = width;
        canvas.height = height;
        ctx = canvas.getContext('2d');

        // create particles
        circles = [];
        for(var x = 0; x < width*0.5; x++) {
            var c = new Circle();
            circles.push(c);
        }
        animate();
    }

    // Event handling
    function addListeners() {
        window.addEventListener('scroll', scrollCheck);
        window.addEventListener('resize', resize);
    }

    function scrollCheck() {
        if(document.body.scrollTop > height) animateHeader = false;
        else animateHeader = true;
    }

    function resize() {
        width = window.innerWidth;
        height = window.innerHeight;
        largeHeader.style.height = height+'px';
        canvas.width = width;
        canvas.height = height;
    }

    function animate() {
        if(animateHeader) {
            ctx.clearRect(0,0,width,height);
            for(var i in circles) {
                circles[i].draw();
            }
        }
        requestAnimationFrame(animate);
    }

    // Canvas manipulation
    function Circle() {
        var _this = this;

        // constructor
        (function() {
            _this.pos = {};
            init();
            console.log(_this);
        })();

        function init() {
            _this.pos.x = Math.random()*width;
            _this.pos.y = height+Math.random()*100;
            _this.alpha = 0.1+Math.random()*0.3;
            _this.scale = 0.1+Math.random()*0.3;
            _this.velocity = Math.random();
        }

        this.draw = function() {
            if(_this.alpha <= 0) {
                init();
            }
            _this.pos.y -= _this.velocity;
            _this.alpha -= 0.0005;
            ctx.beginPath();
            ctx.arc(_this.pos.x, _this.pos.y, _this.scale*10, 0, 2 * Math.PI, false);
            ctx.fillStyle = 'rgba(255,255,255,'+ _this.alpha+')';
            ctx.fill();
        };
    }

})();

If you have a solution in mind, your input would be greatly appreciated! Thank you in advance :)

Answer №1

This snippet of code simplifies the process of drawing triangles on a canvas. If you want to delve deeper into these methods, refer to the canvas API on MDN.

ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x - (width/2) , y + height);
ctx.lineTo(x + (width/2) , y + height);
ctx.fill();

The triangle is drawn from the top (Y axis goes from top to bottom), starts at the left bottom corner, and ends at the right bottom corner.

    1 = (x, y)
  .   .
 .     .
2 . . . 3 = (x + (width/2), y + height)

(function() {

  var width, height, largeHeader, canvas, ctx, circles, target, animateHeader = true;

  // Main
  initHeader();
  addListeners();

  function initHeader() {
    width = window.innerWidth;
    height = window.innerHeight;
    target = {x: 0, y: height};

    largeHeader = document.getElementById('large-header');
    largeHeader.style.height = height+'px';

    canvas = document.getElementById('demo-canvas');
    canvas.width = width;
    canvas.height = height;
    ctx = canvas.getContext('2d');

    // create particles
    circles = [];
    for(var x = 0; x < 100; x++) {
      var c = new Circle();
      circles.push(c);
    }
    animate();
  }

  // Event handling
  function addListeners() {
    window.addEventListener('scroll', scrollCheck);
    window.addEventListener('resize', resize);
  }

  function scrollCheck() {
    animateHeader = document.body.scrollTop < height;
  }

  function resize() {
    width = window.innerWidth;
    height = window.innerHeight;
    largeHeader.style.height = height+'px';
    canvas.width = width;
    canvas.height = height;
  }

  function animate() {
    if(animateHeader) {
      ctx.clearRect(0,0,width,height);
      for(var i in circles) {
        circles[i].draw();
      }
    }
    requestAnimationFrame(animate);
  }

  // Canvas manipulation
  function Circle() {
    var _this = this;

    // constructor
    (function() {
      _this.pos = {};
      init();
      //console.log(_this);
    })();

    function init() {
      _this.pos.x = Math.random()*width;
      _this.pos.y = height+Math.random()*100;
      _this.alpha = 0.1+Math.random()*0.3;
      _this.height = 10+Math.random()*0.3;
      _this.width = 10+Math.random()*0.3;
      _this.velocity = Math.random();
    }

    this.draw = function() {
      if(_this.alpha <= 0) {
        init();
      }
      _this.pos.y -= _this.velocity;
      _this.alpha -= 0.0005;
      ctx.beginPath();
      ctx.moveTo(_this.pos.x, _this.pos.y);
      ctx.lineTo(_this.pos.x - (_this.width/2) , _this.pos.y + _this.height);
      ctx.lineTo(_this.pos.x + (_this.width/2) , _this.pos.y + _this.height);
      ctx.fillStyle = 'rgba(255,255,255,'+ _this.alpha+')';
      ctx.fill();
    };
  }

})();
body {
  overflow-x: hidden;
}
#large-header, #demo-canvas {
  background: #333;
}
#content {
  position: absolute;
  top: 100%;
  padding: 10px;
}
<!DOCTYPE html>
<html>
  <head>
    <script src="https://code.jquery.com/jquery-1.11.1.min.js"></script>
    <meta charset="utf-8">
    <title>JS Bin</title>
  </head>
  <body>
    <div id="large-header">
      <canvas id="demo-canvas"></canvas>
    </div>
    <div id="content">
      <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum</p>
    </div>
  </body>
</html>

jsbin

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

How can I style my tables to have different border spacing between the table head and table body?

When it comes to tables, I want to customize the column spacing in a specific way. I need space between columns in the table header but no gaps between columns in the table body. How can I achieve this by including border space only in the thead section? ...

challenges with Next.js dynamic routing when dealing with spaces

I am facing an issue with accessing dynamic routes using a product name from my API when the name contains spaces. However, I can access the routes without any problem if the product name is just a single word. utils/api.js export async function getProduc ...

Issue with Bootstrap 4 Multi Select Functionality in Modal Not Functioning

Having trouble getting a bootstrap multi-select dropdown to work inside a Bootstrap modal. When the modal opens, the following CSS is affecting the dropdown: select.bs-select-hidden, .bootstrap-select > select.bs-select-hidden, select.selectpicker { ...

Check through an array for any updates whenever a function is called and my react state is altered

I am currently working on a project related to playlists. My goal is to display the image attached to each song whenever that song is clicked from the playlist. Here is the code I have so far... const Component = () => { const value = useContext(DataC ...

Modifying the boolean variable value in aspx.vb code

Recently, I started learning asp.net and I am facing an issue with changing the value of my boolean variable when I click a button. Below is my code: Partial Class Title Dim checker As Boolean Protected Sub Enterbutton1(ByVal sender As Object, ByVal e ...

Is there a way to retrieve an attribute from a nested object in a loop while using VueJS?

Currently, I am facing an issue while trying to access a property within a nested object using a loop in my vuejs project. It's strange because similar nested objects work fine except for one. <template> <div> <tr v-for=" ...

Moving up stacked columns with bootstrap or any other CSS technique

Is there a way to make column [3] move up if column [2] is taller than column [1]? [1][2] [3][4] Check out this bootply example of the layout : http://www.bootply.com/KbAf8UOk9c Currently, there is empty space between column [1] and [3] that I would li ...

The battle between Hover, Focus, and Blur modes intensifies

My goal is to implement 4 different effects on an element: When hovering over the element. When moving away from the element. When focusing on the element. When blurred. However, I'm encountering a conflict where when I focus on the element, the ...

difficulty arises when attempting to invoke a viewmodel from another viewmodel inside a ko.computed function

Is it possible to have two view model functions in my JavaScript where one references the other? I am encountering an error with this setup. Here are my view models: var userViewModel = function (data) { var _self = this; _self.ID = ko.obs ...

Is it possible to style a nested ID with CSS?

Imagine a scenario where you are working within an HTML file that you cannot modify, but you have the ability to only edit the CSS through a stylesheet. Is it possible to target an ID within another ID in the same way you can do with classes? #id1 #id2 {s ...

The slicing of jQuery parent elements

Hey there! I recently created a simulated "Load More" feature for certain elements within divs. However, I've encountered an issue where clicking on the Load More button causes all elements in both my first and second containers to load simultaneously ...

Unable to obtain return value in AngularJS controller or view

I have been working on a geolocation and reverse geocoding application. I have a function that is triggered by a button click to call a function in my controller which then calls my service. While the service is able to retrieve values, I am unable to get ...

Can CSS be used to create curved dashed lines?

Is it possible to achieve dashed lines similar to the ones highlighted in the images below using only CSS? I have a responsive web page built with Bootstrap, and I need the dashed lines to adjust accordingly when the window width changes. https://i.sstat ...

Calculating the product of two input fields and storing the result in a third input field using a for loop

There's a small issue I'm facing. I have implemented a For Loop to generate multiple sets of 3 input fields - (Quantity, Rate, Price). Using a Javascript function, I aim to retrieve the Ids of 'Quantity' and 'Rate', and then d ...

Exploring AngularJS JSON Parsing Techniques (such as utilizing ng-repeat)

My approach to processing json data looks like this: $scope.activities = response.data; console.log($scope.activities.length); var list = []; for (var i = 0; i < $scope.activities.length; i++) { console.log($scope.activities[i].name); list.pus ...

Vue allows a child component to share a method with its parent component

Which approach do you believe is more effective among the options below? [ 1 ] Opting to utilize $emit for exposing methods from child components to parent components $emit('updateAPI', exposeAPI({ childMethod: this.childMethod })) OR [ 2 ] ...

When using Expressjs MVC, encountering difficulties in retrieving data from mongoose in the listAll() function within the router

I'm currently working on implementing MVC-like architecture in Express.js for a very specific scenario. I suspect there may be an issue with promises, but I'm struggling to debug the problem effectively. Here's how the architecture is set u ...

Determine the y-coordinate of terrain in Three.js

I have acquired a Collada model of terrain and now wish to incorporate other models onto this terrain. To achieve this, I believe I need to retrieve the height coordinate (y) of the terrain based on specific x and z coordinates. Can someone please guide ...

Unable to retrieve variable using the require statement

When attempting to access the variable 'app' from the required index.js in my test, I encounter difficulty resolving the 'app' variable. server.js 'use strict'; var supertestKoa = require('supertest-koa-agent'); ...

Which option is more effective: using an id or using !important?

While some say to avoid using the !important rule and others argue that since ids are unique, there is no need to target like #main > #child and you can simply use #child. In my particular case: #main > div{ color: red; } #child{ color: blue;/ ...