언어/Chart.js

[chart.js] 분산형 그래프 포인트를 이미지로

홍시_코딩기록 2024. 3. 16. 13:16

 


1. 포인트 이미지, 테두리 설정

2. hover시에만 이미지로

 

 

📌 포인트 이미지, 테두리 설정

 

- 분산형 차트..! 뭔가 무시무시해보임.

                     usePointStyle: true, // 포인트 스타일 바꾸기 위해서 true
                     pointStyle: image, // 선언된 이미지 가져옴
                     clip: false,  // 그래프 밖으로 이미지 잘리는 거 막기 위해서 false

 

 

const imageBorder = {
                id: 'imageBorder',
                beforeDatasetsDraw(chart, args, plugins) {
                    const {ctx, data} = chart;
                    ctx.save();
                    const x = chart.getDatasetMeta(0).data[0].x;
                    const y = chart.getDatasetMeta(0).data[0].y;
                    const radius = 15;
                    const angle = Math.PI / 180;

                    chart.getDatasetMeta(0).data.forEach((dataPoint, index) => {                        
                        ctx.beginPath();
                        ctx.strokeStyle = data.datasets[0].borderColor[index]; // 차트의 해당하는 테두리 색 가져옴
                        ctx.lineWidth = data.datasets[0].borderWidth; // 차트의 보더width값 가져옴

                        ctx.arc(dataPoint.x, dataPoint.y, radius, 0, angle * 360, false);
                        ctx.stroke();
                    });
                }
            }

- 차트가 그려지기 전에 그려주기 위해서 beforeDatasetsDraw

- x, y로 포인트의 좌표값 구함

- 포인트의 좌표값을 구했지만 차트의 포인트는 여러개니까! 반복문 돌려서 각각의 값에 설정값 넣어줌. 슥슥

 

 

 

(전체코드)

 // 이미지 아이콘
            const image = new Image(25, 25);
            image.src = './emoji.png';
          
            // 이미지 테두리
            const imageBorder = {
                id: 'imageBorder',
                beforeDatasetsDraw(chart, args, plugins) {
                    const {ctx, data} = chart;
                    ctx.save();
                    const x = chart.getDatasetMeta(0).data[0].x;
                    const y = chart.getDatasetMeta(0).data[0].y;
                    const radius = 15;
                    const angle = Math.PI / 180;

                    chart.getDatasetMeta(0).data.forEach((dataPoint, index) => {                        
                        ctx.beginPath();
                        ctx.strokeStyle = data.datasets[0].borderColor[index];
                        ctx.lineWidth = data.datasets[0].borderWidth;

                        ctx.arc(dataPoint.x, dataPoint.y, radius, 0, angle * 360, false);
                        ctx.stroke();
                    });
                }
            }

            new Chart(ctx, {
              type: 'scatter',
              data: {
                datasets: [{
                    label: 'Scatter Dataset',
                    data: [{
                            x: -10,
                            y: 0
                        }, {
                            x: 0,
                            y: 10
                        }, {
                            x: 10,
                            y: 5
                        }, {
                            x: 0.5,
                            y: 5.5
                        }],
                     backgroundColor: [
                        'red',
                        'yellow',
                        'orange',
                        'green'
                     ],
                     borderColor: [
                        'red',
                        'yellow',
                        'orange',
                        'green'
                     ],
                     borderWidth: 3,
                     usePointStyle: true,
                     pointStyle: image,
                     clip: false
                }]
              },
              options: {
                layout: {
                    padding: {
                        right: 20
                    }
                },
                scales: {
                    y: {
                        beginAtZero: true
                    },
                    x: {
                        type: 'linear',
                        position: 'bottom'
                    }
                }
              },
              plugins: [imageBorder]
            });

 

 

📌 hover할때 이미지

- 바뀌는 부분은 여기뿐

                     borderWidth: 3,
                     usePointStyle: true,
                     pointStyle: 'circle',
                     hoverPointStyle : image,
                     clip: false
              options: {
                interaction: {
                    intersect: false,
                    mode: 'nearest',
                },

 

- hover할 때만 포인트를 이미지로 변경하고 싶었다.

- 공식문서에서 찾아봤지만 hoverPointStyle이 없는 것 같다. pointstyle도 있는데 hoverPointStyle도 되지않을까해서 넣어봤는데 됨 ㅎㅎ 

- 근처에 가면 포인트가 이미지로 바뀌게 interaction 설정!

 

 

 

 

 

 

-- 참고 --

https://www.youtube.com/watch?v=TDCNVi5hBFw