d3.js - React Native ART and D3: how to make the corners of d3.path rounded?


Keywords:d3.js 


Question: 

Is there any way to round the corners or a bar I made with d3.path? I am using React Native ART.

Right now I have this:

my square bar

But I want rounded corners. I'm trying to make something like this: my rounded square bar

_createBarChart (x, y, w, h) {
  var path = d3.path.path()
  path.rect(x, y, w, h)
  return path
}

return (
  <View style={styles.container}>
    <Surface width={screen.width} height={200}>
      <Group x={0} y={180}>
        <Shape d={this._createBarChart(7, -35, 70, 35)} fill={color.purple} />
      </Group>
    </Surface>
  </View>
)

1 Answer: 

I use this utility function to draw a rect with some rounded corners (you can specify which corners should not be rounded):

function drawRoundedRect(
  xCoord,
  yCoord,
  width,
  height,
  radius,
  needRoundingTopLeft = true,
  needRoundingTopRight = true,
  needRoundingBottomLeft = true,
  needRoundingBottomRight = true
) {
  let retval;
  retval = 'M' + (xCoord + radius) + ',' + yCoord;
  retval += 'h' + (width - 2 * radius);

  if (needRoundingTopRight) {
    retval += 'a' + radius + ',' + radius + ' 0 0 1 ' + radius + ',' + radius;
  } else { retval += 'h' + radius; retval += 'v' + radius; }

  retval += 'v' + (height - 2 * radius);

  if (needRoundingBottomRight) {
    retval += 'a' + radius + ',' + radius + ' 0 0 1 ' + -radius + ',' + radius;
  } else { retval += 'v' + radius; retval += 'h' + -radius; }

  retval += 'h' + (2 * radius - width);

  if (needRoundingBottomLeft) {
    retval += 'a' + radius + ',' + radius + ' 0 0 1 ' + -radius + ',' + -radius;
  } else { retval += 'h' + -radius; retval += 'v' + -radius; }

  retval += 'v' + (2 * radius - height);

  if (needRoundingTopLeft) {
    retval += 'a' + radius + ',' + radius + ' 0 0 1 ' + radius + ',' + -radius;
  } else { retval += 'v' + -radius; retval += 'h' + radius; }

  retval += 'z';

  return retval;
}

You can create a method in your component with this code and use it this way:

_createBarChart(x, y, w, h) {
  return this._drawRoundedRect(x, y, w, h, 10)
}

_drawRoundedRect(xCoord, yCoord, width, height, radius, needRoundingTopLeft = true, needRoundingTopRight = true, needRoundingBottomLeft = true, needRoundingBottomRight = true) {
    /* code above */
}

return (
  <View style={styles.container}>
    <Surface width={screen.width} height={200}>
      <Group x={0} y={180}>
        <Shape d={this._createBarChart(7, -35, 70, 35)} fill={color.purple} />
      </Group>
    </Surface>
  </View>
)

Check working demo in the hidden snippet below:

function drawRoundedRect(
  xCoord,
  yCoord,
  width,
  height,
  radius,
  needRoundingTopLeft = true,
  needRoundingTopRight = true,
  needRoundingBottomLeft = true,
  needRoundingBottomRight = true
) {
  let retval;
  retval = 'M' + (xCoord + radius) + ',' + yCoord;
  retval += 'h' + (width - 2 * radius);

  if (needRoundingTopRight) {
    retval += 'a' + radius + ',' + radius + ' 0 0 1 ' + radius + ',' + radius;
  } else { retval += 'h' + radius; retval += 'v' + radius; }

  retval += 'v' + (height - 2 * radius);

  if (needRoundingBottomRight) {
    retval += 'a' + radius + ',' + radius + ' 0 0 1 ' + -radius + ',' + radius;
  } else { retval += 'v' + radius; retval += 'h' + -radius; }

  retval += 'h' + (2 * radius - width);

  if (needRoundingBottomLeft) {
    retval += 'a' + radius + ',' + radius + ' 0 0 1 ' + -radius + ',' + -radius;
  } else { retval += 'h' + -radius; retval += 'v' + -radius; }

  retval += 'v' + (2 * radius - height);

  if (needRoundingTopLeft) {
    retval += 'a' + radius + ',' + radius + ' 0 0 1 ' + radius + ',' + -radius;
  } else { retval += 'v' + -radius; retval += 'h' + radius; }

  retval += 'z';

  return retval;
}

d3.select('svg#all-round')
	.append('path')
  .attr('d', drawRoundedRect(0, 0, 50, 50, 10))
  
  d3.select('svg#only-top-round')
	.append('path')
  .attr('d', drawRoundedRect(0, 0, 50, 50, 10, true, true, false, false))
body {
  display: flex;
}

div {
  margin-right: 15px;
}

svg {
  fill: green;
}
<script src=""></script>
<div>
  <h3>Round all:</h3>
  <svg id="all-round" width="60" height="60"></svg>
</div>
<div>
  <h3>Round only top:</h3>
  <svg id="only-top-round" width="60" height="60"></svg>
</div>