pathfit to scale to bound

ghz 8months ago ⋅ 95 views

I am creating svg path and scaling it to a specific dimension. Let's suppose 100x100. I am using d3 to shape the data as per my req.

However, I was wondering, how can I achieve the exact same output as pathStr with pathfit. This is what I tried below.

function degreeToRadian(d) {
    return (d * Math.PI) / 180;
};

function fnData() {
    const data = d3.range(0, 11, 1).map((d) => {
        const angleRadian = degreeToRadian(d);
        return {
            index: d,
            angleDeg: d,
            angleRadian: angleRadian,
            x: Math.cos(angleRadian),
            y: Math.sin(angleRadian)
        }
    });

    return data;
};

const width = 1280;
const height = 720;
const data = fnData();

//------------------------WITH D3------------------------//
const scaleX = d3
    .scaleLinear()
    .range([0, 100])
    .domain(d3.extent(data, (d) => d.x));

const scaleY = d3
    .scaleLinear()
    .range([100, 0])
    .domain(d3.extent(data, (d) => d.y));

const pathStr = d3
    .line()
    .x((d) => scaleX(d.x))
    .y((d) => scaleY(d.y))(data);
  
const pathStr2 = d3.line().x(d=>d.x).y(d=>d.y)(data);  

//------------------------WITH pathfit------------------------//

const base = {
    viewBox: `0 0 ${width} ${height}`,
    preserveAspectRatio: "xMidYMid meet" // the default
};
const pathFitter = new Pathfit(base, undefined, pathStr2).scale_with_aspect_ratio(100, 100);
console.log({d3:pathStr, pathfit:pathFitter});
<script type="text/javascript" src="https://d3js.org/d3.v7.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/pathfit@1.0.4/pathfit.js"></script>

Answers

It looks like you're trying to scale an SVG path to fit within a specific dimension using both D3 and Pathfit libraries. However, there seems to be a discrepancy in the results you're getting between the two approaches.

One possible reason for the discrepancy could be the difference in how D3's d3.line() function and Pathfit library interpret the input data.

In D3, when you use d3.line(), it expects an array of objects with x and y properties representing the coordinates of the points. On the other hand, Pathfit library expects an SVG path string as input.

To ensure consistency between the two approaches, you should provide the same input data format to both D3 and Pathfit. Here's how you can modify your code to achieve that:

const pathStr2 = d3.line().x(d => scaleX(d.x)).y(d => scaleY(d.y))(data);

// Convert pathStr2 to SVG path format
const pathStr2Svg = `M${data[0].x},${data[0].y}` + pathStr2.slice(1);

//------------------------WITH pathfit------------------------//

const base = {
    viewBox: `0 0 ${width} ${height}`,
    preserveAspectRatio: "xMidYMid meet" // the default
};

const pathFitter = new Pathfit(base, undefined, pathStr2Svg).scale_with_aspect_ratio(100, 100);
console.log({d3: pathStr, pathfit: pathFitter.getPathString()});

In this modified version, pathStr2Svg is created by converting the D3-generated path string pathStr2 into SVG path format, which is then passed to the Pathfit library. This should ensure consistency between the D3 and Pathfit results.