ডোনাট (গেজ) এর জন্য কাস্টম ব্যাকগ্রাউন্ড সীমা


9

আমি ( চার্টজ-এসএসগেজ ) উপর ভিত্তি করে একটি গেজ চার্ট ব্যবহার করছি । আমি গেজ সীমা থেকে পৃথক চার্টের জন্য পটভূমির রঙ সেট করতে চাই। চার্টস.জেএস কীভাবে পটভূমিতে রেন্ডার দেয় তা সমস্যা কারণ আমি যে প্লাগইন ব্যবহার করেছি তাতে ব্যাকগ্রাউন্ড সম্পর্কে কোনও কোড নেই। উদাহরণস্বরূপ, আমার সীমাবদ্ধতা রয়েছে [0, 20, 40, 60, 80, 100]। আমি [0-30]সবুজ, [30-70]হলুদ এবং [70-100]লাল করতে সেট করতে চাই । বর্তমান কোড: কোডপেন

এখানে আমার বর্তমান বিকল্পগুলি।

var ctx = document.getElementById("canvas").getContext("2d");
new Chart(ctx, {
    type: "tsgauge",
    data: {
        datasets: [{
            backgroundColor: ["#0fdc63", "#fd9704", "#ff7143"],
            borderWidth: 0,
            gaugeData: {
                value: 7777,
                valueColor: "#ff7143"
            },
            gaugeLimits: [0, 3000, 7000, 10000]
        }]
    },
    options: {
            events: [],
            showMarkers: true
    }
});

এবং ব্যাকগ্রাউন্ডের রঙ নির্ধারণের জন্য আমার পদ্ধতিটি এখানে।

new Chart(ctx, {
    type: "tsgauge",
    data: {
        datasets: [{
            backgroundColor: ["#0fdc63", "#fd9704", "#ff7143"],
            borderWidth: 0,
            gaugeData: {
                value: 50,
                valueColor: "#ff7143"
            },
            gaugeLimits: [0, 20, 40, 60, 80, 100],
            gaugeColors: [{
                min: 0,
                max: 30,
                color: ""
                }, {
                min: 30,
                max: 70,
                color: ""
             },{
                min:70,
                max:100,
                color: ""
             }]
         }]
    },
    options: {
        events: [],
        showMarkers: true
    }
});

বর্তমানে Chart.JSরং মিলে যায় 0থেকে iসীমা 0থেকে i। আমি কাঙ্ক্ষিত রংগুলির সাথে আরও একটি ডামি চার্ট আঁকতে ভেবেছিলাম এবং এটিকে আসল চার্টের উপরে সেট করেছি তবে এটি এটি করার মতো দুষ্টু উপায় বলে মনে হচ্ছে।


হ্যালো, আমি আপনাকে সহায়তা করতে চাই তবে আমার মনে হয় আপনি যা করতে চান তা আমি সম্পূর্ণরূপে অনুসরণ করি না, আপনি কি উওওয়ান্তের প্রত্যাশিত আউটপুটটি কি কোনও চিত্র যুক্ত করতে পারেন? চার্টের পিছনে আপনি কোন পটভূমিটি উল্লেখ করছেন?
স্যারপিল

উত্তর:


3

পূর্ববর্তী সমাধান

এটি অর্জনের জন্য আপনি আপনার ডেটাসেটটি কিছুটা পরিবর্তন করতে পারেন:

backgroundColor: ["green", "green", "green", "yellow", "yellow", "yellow", "yellow", "red", "red", "red"],
gaugeLimits: [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100],

যেহেতু আপনার বর্তমানে gagueLimitsবিস্তৃত হয়েছে 20, তাই আপনি 30 এর সীমা অ্যাক্সেস করতে পারবেন না,

সুতরাং, আমি এখানে যা করেছি তা guageLimitsবিভক্ত হয়ে গেছে 10এবং এখন 30এটি অ্যাক্সেসযোগ্য 70,

রঙগুলি সম্পর্কে, আপনার প্রত্যেকের অ্যারেতে guageLimitsএকটি রঙ প্রয়োজন backgroundColor, আমি সেগুলি সে অনুযায়ী সেট করে রেখেছি, উপরের অ্যারেটি পরীক্ষা করুন। যেহেতু সম্পর্কিত বর্ণগুলির কোনওটিই খালি না থাকতে পারে, আপনি পরবর্তী রঙের সীমাতে না পৌঁছা পর্যন্ত আপনাকে একই রঙ ব্যবহার করতে হবে।

আপডেট সমাধান

আপনার প্রয়োজনীয়তা এখন সাফ:

  • আপনি গেজ লেবেলগুলি খুব স্বাচ্ছন্দ্যপূর্ণ না করতে চান, এজন্যই 20 এর সীমা।
  • এবং আপনি রঙের রেঞ্জগুলি 30 এবং 70 পয়েন্টে আলাদা করতে চান।

এখন, প্রযুক্তিগতভাবে যদি আপনি একটি নির্দিষ্ট বিন্দুতে একটি রঙ পরিসর সেট করতে চান, আপনার gaugeLimitsঅ্যারেতে এটির মান থাকা দরকার , সুতরাং আপনার হ্রাস করা gaugeLimitsঅ্যারে এখন এইরকম হয়ে যায়:

gaugeLimits: [0, 20, 30, 40, 60, 70, 80, 100],

অ্যারেতে পয়েন্টগুলি নির্দিষ্ট করা হওয়ায় আপনি সেই অনুযায়ী রং সেট করতে পারবেন না। সুতরাং, backgroundColorঅ্যারেটি হ'ল:

backgroundColor: ["#0fdc63", "#0fdc63", "#fd9704", "#fd9704", "#fd9704", "#ff7143", "#ff7143"]

এখন, চূড়ান্ত কৌশল

আপনার এখনও স্কেল থেকে 30 এবং 70 টি লুকিয়ে রাখা দরকার, আমি showMarkersআপনার কোডটিতে টগল করার চেষ্টা করেছি , দেখে মনে হচ্ছে এটি পুরোপুরি দৃশ্যমান সংখ্যা স্কেলটিকে সক্ষম বা অক্ষম করে দিয়েছে, আমি স্ট্রিংগুলির একটি অ্যারে সরবরাহ করার চেষ্টা করেছি, তবে এটি কেবল গ্রহণ করেboolean


Chartjs-tsgauge উপলভ্য বিকল্পগুলি সম্পর্কে খুব বেশি ডকুমেন্টেশন সরবরাহ করে না, তাই আমি কোডটি ফাঁকে পেয়েছি এবং পেয়েছিmarkerFormatFn

এটি যা করে তা হ'ল প্যারামিটার হিসাবে একটি ফাংশন নেওয়া এবং আপনি আপনার প্রতিটি চিহ্নিতকারী আইটেমের সাথে কী করবেন তা জানিয়ে একটি ফাংশন সরবরাহ করতে পারেন।

সুতরাং, আমি কোনও ফাংশন সরবরাহ করার জন্য একটি ধারণা নিয়ে এসেছি যা কেবলমাত্র 20 টি দ্বারা বিভাজ্য কোনও সংখ্যা ছাড়াই ব্যতীত অন্যথায় খালি স্ট্রিংটি ফিরিয়ে দিন, এটি এখানে:

markerFormatFn: n => n % 20 === 0 ? n.toString() : '',

স্নিপেট পরীক্ষা করুন:

//Gauge Plugin
(function() {
  if (!window.Chart) {
    return;
  }

  function GaugeChartHelper() {}
  GaugeChartHelper.prototype.setup = function(chart, config) {
    this.chart = chart;
    this.ctx = chart.ctx;
    this.limits = config.data.datasets[0].gaugeLimits;
    this.data = config.data.datasets[0].gaugeData;
    var options = chart.options;
    this.fontSize = options.defaultFontSize;
    this.fontStyle = options.defaultFontFamily;
    this.fontColor = options.defaultFontColor;
    this.ctx.textBaseline = "alphabetic";
    this.arrowAngle = 25 * Math.PI / 180;
    this.arrowColor = config.options.indicatorColor || options.arrowColor;
    this.showMarkers =
      typeof config.options.showMarkers === "undefined" ?
      true :
      config.options.showMarkers;
    if (config.options.markerFormatFn) {
      this.markerFormatFn = config.options.markerFormatFn;
    } else {
      this.markerFormatFn = function(value) {
        return value;
      };
    }
  };
  GaugeChartHelper.prototype.applyGaugeConfig = function(chartConfig) {
    this.calcLimits();
    chartConfig.data.datasets[0].data = this.doughnutData;
    var ctx = this.ctx;
    var labelsWidth = this.limits.map(
      function(label) {
        var text = this.markerFormatFn(label);
        return ctx.measureText(text).width;
      }.bind(this)
    );
    var padding = Math.max.apply(this, labelsWidth) + this.chart.width / 35;
    var heightRatio = this.chart.height / 50;
    chartConfig.options.layout.padding = {
      top: this.fontSize + heightRatio,
      left: padding,
      right: padding,
      bottom: heightRatio * 2
    };
  };
  GaugeChartHelper.prototype.calcLimits = function() {
    var limits = this.limits;
    var data = [];
    var total = 0;
    for (var i = 1, ln = limits.length; i < ln; i++) {
      var dataValue = Math.abs(limits[i] - limits[i - 1]);
      total += dataValue;
      data.push(dataValue);
    }
    this.doughnutData = data;
    var minValue = limits[0];
    var maxValue = limits[limits.length - 1];
    this.isRevers = minValue > maxValue;
    this.minValue = this.isRevers ? maxValue : minValue;
    this.totalValue = total;
  };
  GaugeChartHelper.prototype.updateGaugeDimensions = function() {
    var chartArea = this.chart.chartArea;
    this.gaugeRadius = this.chart.innerRadius;
    this.gaugeCenterX = (chartArea.left + chartArea.right) / 2;
    this.gaugeCenterY =
      (chartArea.top + chartArea.bottom + this.chart.outerRadius) / 2;
    this.arrowLength = this.chart.radiusLength * 2;
  };
  GaugeChartHelper.prototype.getCoordOnCircle = function(r, alpha) {
    return {
      x: r * Math.cos(alpha),
      y: r * Math.sin(alpha)
    };
  };
  GaugeChartHelper.prototype.getAngleOfValue = function(value) {
    var result = 0;
    var gaugeValue = value - this.minValue;
    if (gaugeValue <= 0) {
      result = 0;
    } else if (gaugeValue >= this.totalValue) {
      result = Math.PI;
    } else {
      result = Math.PI * gaugeValue / this.totalValue;
    }
    if (this.isRevers) {
      return Math.PI - result;
    } else {
      return result;
    }
  };
  GaugeChartHelper.prototype.renderLimitLabel = function(value) {
    var ctx = this.ctx;
    var angle = this.getAngleOfValue(value);
    var coord = this.getCoordOnCircle(
      this.chart.outerRadius + this.chart.radiusLength / 2,
      angle
    );
    var align;
    var diff = angle - Math.PI / 2;
    if (diff > 0) {
      align = "left";
    } else if (diff < 0) {
      align = "right";
    } else {
      align = "center";
    }
    ctx.textAlign = align;
    ctx.font = this.fontSize + "px " + this.fontStyle;
    ctx.fillStyle = this.fontColor;
    var text = this.markerFormatFn(value);
    ctx.fillText(
      text,
      this.gaugeCenterX - coord.x,
      this.gaugeCenterY - coord.y
    );
  };
  GaugeChartHelper.prototype.renderLimits = function() {
    for (var i = 0, ln = this.limits.length; i < ln; i++) {
      this.renderLimitLabel(this.limits[i]);
    }
  };
  GaugeChartHelper.prototype.renderValueLabel = function() {
    var label = this.data.value.toString();
    var ctx = this.ctx;
    ctx.font = "30px " + this.fontStyle;
    var stringWidth = ctx.measureText(label).width;
    var elementWidth = 0.75 * this.gaugeRadius * 2;
    var widthRatio = elementWidth / stringWidth;
    var newFontSize = Math.floor(30 * widthRatio);
    var fontSizeToUse = Math.min(newFontSize, this.gaugeRadius);
    ctx.textAlign = "center";
    ctx.font = fontSizeToUse + "px " + this.fontStyle;
    ctx.fillStyle = this.data.valueColor || this.fontColor;
    ctx.fillText(label, this.gaugeCenterX, this.gaugeCenterY);
  };
  GaugeChartHelper.prototype.renderValueArrow = function(value) {
    var angle = this.getAngleOfValue(
      typeof value === "number" ? value : this.data.value
    );
    this.ctx.globalCompositeOperation = "source-over";
    this.renderArrow(
      this.gaugeRadius,
      angle,
      this.arrowLength,
      this.arrowAngle,
      this.arrowColor
    );
  };
  GaugeChartHelper.prototype.renderSmallValueArrow = function(value) {
    var angle = this.getAngleOfValue(value);
    this.ctx.globalCompositeOperation = "source-over";
    this.renderArrow(
      this.gaugeRadius - 1,
      angle,
      this.arrowLength - 1,
      this.arrowAngle,
      this.arrowColor
    );
  };
  GaugeChartHelper.prototype.clearValueArrow = function(value) {
    var angle = this.getAngleOfValue(value);
    this.ctx.lineWidth = 2;
    this.ctx.globalCompositeOperation = "destination-out";
    this.renderArrow(
      this.gaugeRadius - 1,
      angle,
      this.arrowLength + 1,
      this.arrowAngle,
      "#FFFFFF"
    );
    this.ctx.stroke();
  };
  GaugeChartHelper.prototype.renderArrow = function(
    radius,
    angle,
    arrowLength,
    arrowAngle,
    arrowColor
  ) {
    var coord = this.getCoordOnCircle(radius, angle);
    var arrowPoint = {
      x: this.gaugeCenterX - coord.x,
      y: this.gaugeCenterY - coord.y
    };
    var ctx = this.ctx;
    ctx.fillStyle = arrowColor;
    ctx.beginPath();
    ctx.moveTo(arrowPoint.x, arrowPoint.y);
    coord = this.getCoordOnCircle(arrowLength, angle + arrowAngle);
    ctx.lineTo(arrowPoint.x + coord.x, arrowPoint.y + coord.y);
    coord = this.getCoordOnCircle(arrowLength, angle - arrowAngle);
    ctx.lineTo(arrowPoint.x + coord.x, arrowPoint.y + coord.y);
    ctx.closePath();
    ctx.fill();
  };
  GaugeChartHelper.prototype.animateArrow = function() {
    var stepCount = 30;
    var animateTimeout = 300;
    var gaugeValue = this.data.value - this.minValue;
    var step = gaugeValue / stepCount;
    var i = 0;
    var currentValue = this.minValue;
    var interval = setInterval(
      function() {
        i++;
        this.clearValueArrow(currentValue);
        if (i > stepCount) {
          clearInterval(interval);
          this.renderValueArrow();
        } else {
          currentValue += step;
          this.renderSmallValueArrow(currentValue);
        }
      }.bind(this),
      animateTimeout / stepCount
    );
  };
  Chart.defaults.tsgauge = {
    animation: {
      animateRotate: true,
      animateScale: false
    },
    cutoutPercentage: 95,
    rotation: Math.PI,
    circumference: Math.PI,
    legend: {
      display: false
    },
    scales: {},
    arrowColor: "#444"
  };
  Chart.controllers.tsgauge = Chart.controllers.doughnut.extend({
    initialize: function(chart) {
      var gaugeHelper = (this.gaugeHelper = new GaugeChartHelper());
      gaugeHelper.setup(chart, chart.config);
      gaugeHelper.applyGaugeConfig(chart.config);
      chart.config.options.animation.onComplete = function(chartElement) {
        gaugeHelper.updateGaugeDimensions();
        gaugeHelper.animateArrow();
      };
      Chart.controllers.doughnut.prototype.initialize.apply(this, arguments);
    },
    draw: function() {
      Chart.controllers.doughnut.prototype.draw.apply(this, arguments);
      var gaugeHelper = this.gaugeHelper;
      gaugeHelper.updateGaugeDimensions();
      gaugeHelper.renderValueLabel();
      if (gaugeHelper.showMarkers) {
        gaugeHelper.renderLimits();
      }
      gaugeHelper.renderSmallValueArrow(gaugeHelper.minValue);
    }
  });
})();

//Chart setup

var ctx = document.getElementById("chart3").getContext("2d");
new Chart(ctx, {
  type: "tsgauge",
  data: {
    datasets: [{
      backgroundColor: ["#0fdc63", "#0fdc63", "#fd9704", "#fd9704", "#fd9704", "#ff7143", "#ff7143"],
      borderWidth: 0,
      gaugeData: {
        value: 50,
        valueColor: "#ff7143"
      },
      gaugeLimits: [0, 20, 30, 40, 60, 70, 80, 100],
    }]
  },
  options: {
    events: [],
    showMarkers: true,
    markerFormatFn: n => n % 20 === 0 ? n.toString() : '',
  }
});
.gauge {
  width: 500px;
  height: 400px;
}
<link href="https://cdn.jsdelivr.net/npm/chart.js@2.9.2/dist/Chart.min.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/chart.js@2.9.2/dist/Chart.bundle.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>


<div class="gauge">
  <canvas id="chart3"></canvas>
</div>


"এখন বর্ণগুলি সম্পর্কে, আপনার প্রতিটি গ্যুইজলিমেটগুলির ব্যাকগ্রাউন্ড কালার অ্যারেতে একটি রঙের প্রয়োজন" এটি আমি করার চেষ্টা করছি না। বর্তমানে, যখন জিগাইজলিটগুলি অঙ্কন করা হয় তখন তার সূচিটি পরীক্ষা করে এবং ব্যাকগ্রাউন্ড কালার [সূচী ]টিকে তার পটভূমির রঙ হিসাবে ব্যবহার করে। আমি প্রশ্নের মধ্যে দেখা হিসাবে গেজেডিয়ান সম্পত্তি অনুযায়ী পটভূমি আঁকতে চাই। এবং আপনি যদি কৌতূহলী হন তবে আমি কেন এটি চাই? কারণ আমি "10-15-20-25-30-35 ... ইত্যাদি" যেমন চার্টে খুব বেশি লেবেল দেখাতে চাই না।
kenarsuleyman

@Kenarsuleyman এটি কাজ করে? যদি তা হয় তবে আপনি উত্তরটি স্বীকৃত হিসাবে চিহ্নিত করতে পারেন :)
তৌকীর

হ্যাঁ, এটি পুরোপুরি কাজ করে। প্রচেষ্টার জন্য অনেক ধন্যবাদ। আমি অন্য একটি কাজের সাথে খুব ব্যস্ত ছিলাম সে সম্পর্কে দুঃখিত।
kenarsuleyman
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.