NickDevil
NickDevil

Reputation: 185

elements on ellipse edge in d3js

I try put images to oval edge. But they are to a large extent on the poles. I have oval:

  var oval = group.append("ellipse")
            .attr("cx", this.svgWidth / 2)
            .attr("cy", this.svgHeight / 2)
            .attr("rx", this.rx)
            .attr("ry", this.ry)
            .style("stroke", "#BCBBB6")
            .style("stroke-width", "3px")
            .style("fill", "transparent");

and i have image coordinates:

var imgX = Math.cos(that.angle * j) * that.rx - this.model.radius;
var imgY = Math.sin(that.angle * j) * that.ry - this.model.radius;

How can I arrange them evenly? enter image description here

Upvotes: 1

Views: 857

Answers (1)

MR Zamani
MR Zamani

Reputation: 1423

You cannot add image to ellipse tag but you can set image to ellipse background, to add picture to position you mention, Create circle then set image to background of them like this :

var oval = group.append("ellipse")
        .attr("cx", this.svgWidth / 2)
        .attr("cy", this.svgHeight / 2)
        .attr("rx", this.rx)
        .attr("ry", this.ry)
        .style("stroke", "#BCBBB6")
        .style("stroke-width", "3px")
        .style("fill", "transparent");

oval.selectAll("circle")
        .append("circle")
        .attr("cx" ,imgX )
        .attr("cy",imgY)
        .attr("r","8px")
        .attr("fill","Url(#img)");

var imgX = Math.cos(that.angle * j) * that.rx - this.model.radius;
var imgY = Math.sin(that.angle * j) * that.ry - this.model.radius;

Update1

To get the real position you have to change Polar angle to Cartesian.

var imgX = Math.cos((that.angle)*Math.PI * j/180.0) * that.rx - this.model.radius;
var imgY = Math.sin((that.angle)*Math.PI * j/180.0) * that.ry - this.model.radius;  

Update 2

I create a sample like you asked, Hope to help you.

    var width = 600, height = 600;
    var rx = 200, ry = 150;
    var circleNumbers = 20;

    var svg = d3.select("body").append("svg")
        .attr("width", width).attr("height", height)
        .attr("transform", "translate(0,150)");

    var ellipse = svg.append("ellipse")
        .attr("cx", width / 2)
        .attr("cy", height / 2)
        .attr("rx", rx)
        .attr("ry", ry)
        .style("stroke", "#BCBBB6")
        .style("stroke-width", "3px")
        .style("fill", "transparent");
    var degree = 360 / circleNumbers;

    for (var i = 0; i < circleNumbers; i++) {
        var circlePosition = polarToCartesian(width / 2, height / 2, rx, ry, i * degree);
        svg.append("circle")
            .attr("cx", circlePosition.x)
            .attr("cy", circlePosition.y)
            .attr("r", "8px")
            .attr("fill", "red");
    }

This function return position on ellipse with specific degree:

     function polarToCartesian(centerX, centerY, radiusX, radiusY, angleInDegrees) {

        var angleInRadians = (angleInDegrees* Math.PI / 180.0);


        return {
            x: centerX + (radiusX * Math.cos(angleInRadians)),
            y: centerY + (radiusY * Math.sin(angleInRadians))
        };
    }

Complete jsfiddle here.

Update 3

I made some changes to PolarToCartesian() function and it make the ellipse better.I changed the begin Angle to -90 and it's seem better.

        function polarToCartesian(centerX, centerY, radiusX, radiusY, angleInDegrees) {

        var angleInRadians = ((angleInDegrees-90)* Math.PI / 180.0);


        return {
            x: centerX + (radiusX * Math.cos(angleInRadians)),
            y: centerY + (radiusY * Math.sin(angleInRadians))
        };
    }

Complete jsfiddle here.

Upvotes: 1

Related Questions