ปรับขนาดแคนวาส Chart.js


87

ใน ( ข้อผิดพลาดพื้นที่ทำงานของ Android WebView HTML5 ) ฉันโพสต์คำถามเกี่ยวกับการลงจุดกราฟโดยใช้ไลบรารี Graph.js ปัญหาที่ฉันมีตอนนี้คือถ้าฉันเรียกใช้ฟังก์ชันเพื่อลงจุดกราฟหลาย ๆ ครั้งผืนผ้าใบจะปรับขนาดทุกครั้ง ทุกครั้งที่กราฟถูกวาดใหม่เป็นผืนผ้าใบเดียวกันขนาดของกราฟจะเปลี่ยนไปด้วย ฉันลองตั้งขนาดของผืนผ้าใบด้วย แต่ไม่ประสบความสำเร็จ

อะไรคือสาเหตุ? ทำไมผ้าใบถึงปรับขนาดทุกครั้ง?


ตอนนี้เป็นหน้าเฉพาะในเว็บไซต์ officiel ของ Chart.js ที่นี่: chartjs.org/docs/latest/general/responsive.htmlทดสอบโซลูชันแล้วและใช้งานได้ดี
Amine27

คำตอบ:


178

ฉันมีปัญหามากมายกับเรื่องนี้เพราะหลังจากนั้นกราฟิกลายเส้นของฉันก็ดูแย่มากเมื่อวางเมาส์ค้างไว้และฉันพบวิธีที่ง่ายกว่านี้หวังว่ามันจะช่วยได้ :)

ใช้ตัวเลือก Chart.js เหล่านี้:

// Boolean - whether or not the chart should be responsive and resize when the browser does.

responsive: true,

// Boolean - whether to maintain the starting aspect ratio or not when responsive, if set to false, will take up entire container

maintainAspectRatio: false,

ขอบคุณ @NoFlag สำหรับคำตอบ สำหรับฉันแอตทริบิวต์ความสูงและความกว้างไม่ได้ถูกนำไปใช้กับผืนผ้าใบในกรณีที่ทุกคนมองหาวิธีแก้ปัญหาในการพยายามปรับขนาดผ้าใบให้ลองตั้งค่า responsive to true * Chart.defaults.global.responsive = false *
sghosh968

14
อย่าลืมว่าเพื่อให้วิธีนี้ทำงานได้อย่างถูกต้องคุณต้องวางผ้าใบในตำแหน่ง<div>และกำหนดความสูงและ / หรือความกว้างตามที่กล่าวไว้<div>แทนผืนผ้าใบ
totymedli

2
ค่าสถานะเหล่านี้ถูกตั้งค่าเป็นค่าเริ่มต้นtrueดังนั้นคุณจึงไม่จำเป็นต้องแตะต้อง: chartjs.org/docs/latest/general/responsive.html
João Pimentel Ferreira

นอกจากนี้ให้กำหนดความกว้างและความสูงของผ้าใบด้วย จากนั้นก็ใช้งานได้ดี ขอบคุณ
Mazhar MIK

63

สิ่งที่เกิดขึ้นคือ Chart.js คูณขนาดของผืนผ้าใบเมื่อมีการเรียกใช้จากนั้นพยายามที่จะลดขนาดโดยใช้ CSS จุดประสงค์เพื่อให้กราฟความละเอียดสูงขึ้นสำหรับอุปกรณ์ที่มีความละเอียดสูง

ปัญหาคือมันไม่ได้ตระหนักว่าได้ทำสิ่งนี้ไปแล้วดังนั้นเมื่อเรียกว่าครั้งต่อเนื่องมันจะคูณขนาดที่มีอยู่แล้ว (สองเท่าหรือเท่าไหร่ก็ได้) อีกครั้งจนกว่าสิ่งต่างๆจะเริ่มแตก (สิ่งที่เกิดขึ้นจริงคือการตรวจสอบว่าควรเพิ่มพิกเซลให้กับผืนผ้าใบมากขึ้นหรือไม่โดยการเปลี่ยนแอตทริบิวต์ DOM สำหรับความกว้างและความสูงถ้าควรให้คูณด้วยปัจจัยบางอย่างโดยปกติจะเป็น 2 จากนั้นเปลี่ยนสิ่งนั้นแล้วเปลี่ยนสไตล์ css เพื่อรักษาขนาดเดียวกันบนหน้า)

ตัวอย่างเช่นเมื่อคุณเรียกใช้ครั้งเดียวและตั้งค่าความกว้างและความสูงของผ้าใบเป็น 300 จะตั้งค่าเป็น 600 จากนั้นเปลี่ยนแอตทริบิวต์ style เป็น 300 ... แต่ถ้าคุณเรียกใช้อีกครั้งจะเห็นว่าความกว้างและความสูง DOM คือ 600 (ตรวจสอบคำตอบอื่น ๆ สำหรับคำถามนี้เพื่อดูว่าทำไม) จากนั้นตั้งค่าเป็น 1200 และความกว้าง css และความสูงเป็น 600

ไม่ใช่วิธีแก้ปัญหาที่หรูหราที่สุด แต่ฉันแก้ไขปัญหานี้ในขณะที่ยังคงรักษาความละเอียดที่เพิ่มขึ้นสำหรับอุปกรณ์เรตินาโดยเพียงแค่ตั้งค่าความกว้างและความสูงของผืนผ้าใบด้วยตนเองก่อนที่จะเรียกต่อเนื่องไปยัง Chart.js

var ctx = document.getElementById("canvas").getContext("2d");
ctx.canvas.width = 300;
ctx.canvas.height = 300;
var myDoughnut = new Chart(ctx).Doughnut(doughnutData);

1
ฉันเจอข้อผิดพลาดนี้: Uncaught ReferenceError: doughnutData is not defined
Dulith De Costa

11
เอ่อ ใช่นั่นเป็นเพียงตัวแปรตัวยึดตำแหน่งตรงนั้นเนื่องจากฉันไม่รู้ว่าคุณพยายามสร้างกราฟข้อมูลใด
jcmiller11

27

สิ่งนี้ใช้ได้กับฉัน:

<body>
    <form>
        [...]
        <div style="position:absolute; top:60px; left:10px; width:500px; height:500px;">
            <canvas id="cv_values"></canvas>

            <script type="text/javascript">
                var indicatedValueData = {
                    labels: ["1", "2", "3"],
                    datasets: [
                        {
                            [...]
                        };

                var cv_values = document.getElementById("cv_values").getContext("2d");
                var myChart = new Chart(cv_values, { type: "line", data: indicatedValueData });
            </script>
        </div>
    </form>
</body>

ข้อเท็จจริงที่สำคัญก็คือเราต้องกำหนดขนาดของผืนผ้าใบในแท็ก div


ตกลง! เพียงวางผ้าใบไว้ใน div จากนั้นตรวจสอบให้แน่ใจว่าตัวเลือกสำหรับ 'responsive' ไม่เป็นเท็จ (เป็นจริงตามค่าเริ่มต้น) จากนั้นใช้กฎการปรับขนาดกับ div
NoelB

20

ใน IOS และ Android เบราว์เซอร์จะซ่อนแถบเครื่องมือเมื่อคุณกำลังเลื่อนดังนั้นจึงเปลี่ยนขนาดของหน้าต่างที่สลับลีดชาร์ต js เพื่อปรับขนาดกราฟ วิธีแก้ปัญหาคือการรักษาอัตราส่วน

var options = { 
    responsive: true,
    maintainAspectRatio: true
}

วิธีนี้จะช่วยแก้ปัญหาของคุณได้


6

ตามที่ jcmiller11 แนะนำการตั้งค่าความกว้างและความสูงช่วยได้ วิธีแก้ปัญหาที่ดีกว่าเล็กน้อยคือการดึงความกว้างและความสูงของผืนผ้าใบก่อนวาดแผนภูมิ จากนั้นใช้ตัวเลขเหล่านั้นในการกำหนดแผนภูมิในการวาดแผนภูมิใหม่แต่ละครั้งในภายหลัง สิ่งนี้ทำให้แน่ใจว่าไม่มีค่าคงที่ในโค้ดจาวาสคริปต์

ctx.canvas.originalwidth = ctx.canvas.width;
ctx.canvas.originalheight = ctx.canvas.height;

function drawchart() {
    ctx.canvas.width = ctx.canvas.originalwidth;
    ctx.canvas.height = ctx.canvas.originalheight;

    var chartctx = new Chart(ctx);
    myNewBarChart = chartctx.Bar(data, chartSettings); 
}

ขออภัยคุณช่วยอธิบายวิธีการทำงานนี้ได้ไหม ตัวอย่างเช่นฉันเปิดหน้าแล้วผืนผ้าใบมีขนาดเดียว แต่ถ้าฉันปรับขนาดหน้าต่างและผืนผ้าใบจะมีขนาดที่แตกต่างกัน (และน่าจะไม่ต้องการขนาดดั้งเดิมเพราะเป็นขนาดก่อนหน้าของหน้าต่าง)?
kiradotee

6

ฉันต้องใช้คำตอบหลาย ๆ คำรวมกันที่นี่พร้อมกับการปรับแต่งเล็กน้อย

ขั้นแรกคุณจำเป็นต้องห่อองค์ประกอบผืนผ้าใบไว้ในคอนเทนเนอร์ระดับบล็อก ฉันจะบอกคุณไม่ได้ให้องค์ประกอบผ้าใบมีพี่น้องใด ๆ ปล่อยให้มันเป็นเด็กขี้เหงาเพราะมันดื้อและเอาแต่ใจ (กระดาษห่อหุ้มอาจไม่จำเป็นต้องมีข้อ จำกัด ในการปรับขนาดใด ๆ แต่เพื่อความปลอดภัยควรใช้ความสูงสูงสุดกับมันเพื่อความปลอดภัย)

หลังจากมั่นใจว่าตรงตามเงื่อนไขก่อนหน้าเมื่อเริ่มต้นแผนภูมิตรวจสอบให้แน่ใจว่าได้ใช้ตัวเลือกต่อไปนี้:

var options = { 
    "responsive": true,
    "maintainAspectRatio": false
}

หากคุณต้องการปรับความสูงของแผนภูมิให้ดำเนินการที่ระดับองค์ประกอบผ้าใบ

<canvas height="500"></canvas>

อย่าพยายามจัดการกับเด็กในลักษณะอื่นใด สิ่งนี้ควรส่งผลให้ได้แผนภูมิที่จัดวางอย่างเหมาะสมและน่าพอใจซึ่งอยู่ในเปลอย่างสงบ


3

ฉันมีปัญหาที่คล้ายกันและพบคำตอบของคุณ .. ในที่สุดฉันก็มาถึงวิธีแก้ปัญหา

ดูเหมือนว่าแหล่งที่มาของ Chart.js จะมีดังต่อไปนี้ (น่าจะเป็นเพราะไม่ควรแสดงผลซ้ำและกราฟที่แตกต่างกันโดยสิ้นเชิงในผืนผ้าใบเดียวกัน):

    //High pixel density displays - multiply the size of the canvas height/width by the device pixel ratio, then scale.
if (window.devicePixelRatio) {
    context.canvas.style.width = width + "px";
    context.canvas.style.height = height + "px";
    context.canvas.height = height * window.devicePixelRatio;
    context.canvas.width = width * window.devicePixelRatio;
    context.scale(window.devicePixelRatio, window.devicePixelRatio);
}

วิธีนี้ใช้ได้ดีหากมีการเรียกครั้งเดียว แต่เมื่อคุณวาดซ้ำหลายครั้งคุณจะเปลี่ยนขนาดขององค์ประกอบ DOM ของผ้าใบหลายครั้งทำให้เกิดการปรับขนาดใหม่

หวังว่าจะช่วยได้!


1

หากใครกำลังมีปัญหาฉันพบวิธีแก้ปัญหาที่ไม่เกี่ยวข้องกับการเสียสละการตอบสนองเป็นต้น

เพียงห่อผืนผ้าใบของคุณในคอนเทนเนอร์ div (ไม่มีสไตล์) และรีเซ็ตเนื้อหาของ div เป็นผืนผ้าใบว่างด้วย ID ก่อนที่จะเรียกตัวสร้างแผนภูมิ

ตัวอย่าง:

HTML:

<div id="chartContainer">
    <canvas id="myChart"></canvas>
</div>

JS:

$("#chartContainer").html('<canvas id="myChart"></canvas>');
//call new Chart() as usual

1

ฉันพยายามปรับขนาด Canvas โดยใช้ jQuery แต่มันไม่ได้ผล ฉันคิดว่าCSS3เป็นตัวเลือกที่ดีที่สุดที่คุณสามารถลองใช้ได้หากคุณต้องการเลื่อนเมาส์ไปที่ระดับหนึ่ง

กำลังติดตามตัวเลือกโฮเวอร์จากลิงค์ codepan อื่น ๆ :

.style_prevu_kit:hover{
    z-index: 2;
    -webkit-transition: all 200ms ease-in;
    -webkit-transform: scale(1.5);
    -ms-transition: all 200ms ease-in;
    -ms-transform: scale(1.5);   
    -moz-transition: all 200ms ease-in;
    -moz-transform: scale(1.5);
    transition: all 200ms ease-in;
    transform: scale(1.5);
}

ตามลิงค์ codepan ของฉัน:

https://codepen.io/hitman0775/pen/XZZzqN


1

ฉันมีปัญหาเดียวกัน ฉันสามารถแก้ไขได้โดยการตั้งค่าตัวเลือก:

responsive: false,
maintainAspectRatio: true,
showScale: false,

และใน css ให้กำหนดความกว้างของคอนเทนเนอร์ div เช่นเดียวกับผืนผ้าใบ:

    #canvasContainer { 
      width: 300px;
    }
    
    canvas {
      width: 300px;
    }


0

ฉันมีปัญหาการปรับขนาดเดียวกันโดยใช้ Angular CLI สามารถทำให้มันใช้งานได้โดยลบบรรทัดนี้ออกจาก index.html:

<script src="node_modules/chart.js/dist/Chart.bundle.min.js"></script>

จากนั้นในไฟล์ angular-cli.json ในส่วนสคริปต์โดยใช้สิ่งนี้:

"scripts": ["../node_modules/chart.js/dist/Chart.bundle.min.js"]

ที่มา : mikebarr58



-6
 let canvasBox = ReactDOM.findDOMNode(this.refs.canvasBox);
 let width = canvasBox.clientWidth;
 let height = canvasBox.clientHeight;
 let charts = ReactDOM.findDOMNode(this.refs.charts);
 let ctx = charts.getContext('2d');
 ctx.canvas.width = width;
 ctx.canvas.height = height;
 this.myChart = new Chart(ctx);
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.