block by GerHobbelt 3671592

Help on mapping to Cartesian coordinate (log scale)

Full Screen

script.js

//Width and height
var w = 200;
var h = 200;
var padding = 8;
var scale_padding = 20; // space to show axes


var dataset = [
 [80, 20, 10, 60] ];  // x, y, w, h


//Create scale functions
var xScale = d3.scale.log()
    .domain([10, d3.max(dataset, function (d) {
        return (100);
    })])
    .range([padding + scale_padding, w - padding]);

var yScale = d3.scale.log()
    .domain([10, d3.max(dataset, function (d) {
        return (100);
    })])
    .range([h - padding - scale_padding, padding]);

//Define X axis
var xAxis = d3.svg.axis()
    .scale(xScale)
    .orient("bottom")
    // log axis has very ugly tickFormat by default (IMHO)
    .tickFormat(function(d) {
      if (d < 30 || d == 50 || d >= 100)
        return String(d);
      return "";
    })
    .ticks(5);

//Define Y axis
var yAxis = d3.svg.axis()
    .scale(yScale)
    .orient("left")
    // log axis has very ugly tickFormat by default (IMHO)
    .tickFormat(function(d) {
      if (d < 30 || d == 50 || d >= 100)
        return String(d);
      return "";
    })
    .ticks(5);

//Create SVG element
var svg = d3.select("body")
    .append("svg")
    .attr("width", w)
    .attr("height", h);

//Create circles
svg.selectAll("rect")
    .data(dataset)
    .enter()
    .append("rect")
/*
Your y-axis is -linear and SVG doesn't accept negative widths, not does it accept x2/y2 < x1/y1 if you
would use <rect x1 y1 x2 y2> instead, so coordinate pair flipping is in order...

This is the way to do it, particularly important when your scales are not linear (but, say, logarithmic),
but keep in mind that YOU must still guarantee that those width & hieight values are always positive!

Of course, such work might best be done in the preparation phase rather than right here.
*/
    .attr("x", function (d) {
        var x = Math.min(xScale(d[0]), xScale(d[0] + d[2]));
        return x;
    })
    .attr("y", function (d) {
        var y = Math.min(yScale(d[1]), yScale(d[1] + d[3]));
        return y;
    })
    .attr("width", function (d) {
        // return xScale(d[2]);  -- only works like that for +linear scale;
        var x2 = Math.max(xScale(d[0]), xScale(d[0] + d[2]));
        var x1 = Math.min(xScale(d[0]), xScale(d[0] + d[2]));
        return x2 - x1;
    })
    .attr("height", function (d) {
        var y2 = Math.max(yScale(d[1]), yScale(d[1] + d[3]));
        var y1 = Math.min(yScale(d[1]), yScale(d[1] + d[3]));
        return y2 - y1;
    });

//Create X axis
svg.append("g")
    .attr("class", "axis")
    .attr("transform", "translate(0," + (h - padding - scale_padding) + ")")
    .call(xAxis);

//Create Y axis
svg.append("g")
    .attr("class", "axis")
    .attr("transform", "translate(" + (padding + scale_padding) + ",0)")
    .call(yAxis);

index.html

<!DOCTYPE html>
<html>
  <head>
    <title>Test</title>
    <script type="text/javascript" src="//mbostock.github.com/d3/d3.js"></script>
    <link type="text/css" rel="stylesheet" href="style.css"/>
  </head>
  <body>
    <div id="chart"></div>
    <script type="text/javascript" src="script.js"></script>
  </body>
</html>

style.css

.axis text, .origintext {
  font: 10px sans-serif;
}
  
.axis path, .axis line {
  fill: none;
  stroke: #000;
  shape-rendering: crispEdges;
}