Search code examples
javascriptstringvue.jsgradientlinear-gradients

generating manual linear gradient in vue with the color ,percentage and degree input


I am trying to create a manual linear gradient from color,degree and percentage input.User can add as much color as they want. What i want to do is user will pick the degree.Then user will select a color and percentage.When the user click addButton it will be concatinated with string and this way user will concatinate the color and percentage as much as they want and the final value will be something like this:

linear-gradient(0deg, #0359b5ff 0%, #f6ce01ff 50%, #f6ce01ff 100%)  

Here is my template where there is a color picker,percentage and degree input.onclick the add button it will generate value in the final Gradient input box

<template>
      <VContainer class="mx-5 fluid align-self-start">
          <div class="d-flex">
            <label>
              Final gradient
            </label>
            <VTextField
              v-model="gradient"
              filled
              flat
              autofocus
              @blur="$v.gradient.$touch()"
            >
            </VTextField>
          </div>
          <div class="d-flex">
            <label>
              Percentage
            </label>
            <input
              style="border:1px solid black"
              v-model="percentage"
              type="number"
              @change="onPercentage()"
            >
          </div>
          <div class="d-flex">
            <label>
              Degree
            </label>
            <input
              style="border:1px solid black"
              v-model="degree"
              type="number"
            >
          </div>
  
          <input
            v-model="gradientColor"
            type="color"
            @change="onChange()"
          >
          <div class="container">
            <div class="button-group">
              <div>
                <VBtn
                  @click="addColor"
                  class="d-flex mx-auto mt-6"
                  width="137px"
                  height="40px"
                  color="primary"
                >
                  addColor
                </VBtn>
                <button
                  @click="addColor"
                />
              </div>
            </div>
          </div>
     </VContainer>
    
    </template>

this is my data value:

data() {
    return {
      degree: 0,
      coloring: ' ',
      gradientColor: ' ',
      primaryColor: ' ',
      percentage: 0,
  
    };
  },

In the computed gradient final output is generated

computed: {
    gradient() {
      let colors = 'linear-gradient(';
      colors += `${(this.degree)}deg`;
      colors += this.gradientColor + this.percentage;
      colors += ')';
      return colors;
    },
    primary() {
      let colors = ' ';
      colors += this.primaryColor;
      return colors;
    },
}

and here is all the method.onClick the addColor percentage and color value will be concatinated

methods: {
 onChange(val:string) {
      this.primaryColor = `${(val)}`;
    },
    onPercentage(val:string) {
      this.primaryColor = `${(val)}`;
    },
    addColor() {
      this.gradientColor.concat(this.primaryColor);
      this.primaryColor = '';
    },
}

I dont want use an array for this.I want the value would be added in a single variable string.But somehow i am not being able to do it.How can i do it to work?


Solution

  • To start off you can use template literal here and that would shorten your code quite a bit.

    computed: {
    gradient() {
      let colors = 'linear-gradient(';
      colors += `${(this.degree)}deg`;
      colors += this.gradientColor + this.percentage;
      colors += ')';
      return colors;
    },
    

    I think using array to store the selected color and percentage values works nicely here because you can then stringify your array and add commas (only where you need them) by using .join(', ').

      computed: {
        gradient() {
          return `linear-gradient(${this.degree}deg, ${this.colors.join(", ")})`;
        },
      },
    

    As for solving this without using arrays it becomes more cumbersome. You'd have to remove the last comma by searching for its index and then replacing it with a blank. Built-in string method lastIndexOf(',') would come in handy here.

    Here's the code to make it work with arrays. Commented out is the code to make it work just with string minus the last comma deletion. I'm sure you can figure that out yourself 😉

    data() {
        return {
          degree: 0,
          gradientColor: "",
          selectedColor: "#000",
          percentage: 0,
          colors: [],
          // colors: "",
        };
      },
      computed: {
        gradient() {
          return `linear-gradient(${this.degree}deg, ${this.colors.join(", ")})`;
          // return `linear-gradient(${this.degree}deg, ${this.colors} )`;
        },
      },
      methods: {
        addColor() {
          this.colors.push(this.selectedColor + " " + this.percentage + "%");
          //  this.colors += `${this.selectedColor}  ${this.percentage}% ,`;
        },
      },
    

    Markup:

    <template>
      <div class="mx-5 fluid align-self-start">
        <div class="d-flex">
          <label> Final gradient </label>
          <input
            style="width: 100%"
            v-model="gradient"
            @blur="$v.gradient.$touch()"
          />
        </div>
        <div class="d-flex">
          <label> Percentage </label>
          <input
            style="border: 1px solid black"
            v-model="percentage"
            type="number"
          />
        </div>
        <div class="d-flex">
          <label> Degree </label>
          <input style="border: 1px solid black" v-model="degree" type="number" />
        </div>
    
        <input v-model="selectedColor" type="color" />
        <div class="container">
          <div class="button-group">
            <div>
              <button
                @click="addColor"
                class="d-flex mx-auto mt-6"
                width="137px"
                height="40px"
                color="primary"
              >
                addColor
              </button>
            </div>
          </div>
        </div>
      </div>
    </template>
    

    PS: I removed @change methods as you already bind them to degree and selectedColor using v-model.