Wimal Weerawansa
Wimal Weerawansa

Reputation: 157

How to draw rounded corner rectangle in React Native ART

I'm using react-native ART library to draw scalable vector elements in my mobile app, ART is the perfect library due to it can be animated and morph easily with its own tools. But ART don't have custom elements like SVG's Circle, Rect etch..., ART have only one type called Shape and is powerful enough to create almost any shapes. But I'm having difficulties with drawing a scalable rounded cornered rectangle with Shape.

import React from 'react'
import PropTypes from 'prop-types'
import {ART} from 'react-native'

const {Group, Shape} = ART

export default class Graphics extends React.Component{
   render(){
      const {x, y, width, height, fill, stroke} = this.props;
      const d = `M0,0L${width},0L${width},${height}L0,${height}L0,0z`
      return(
        <Group x={x} y={y}>
           <Path d={d} fill={fill} stroke={stroke}>
        </Group>
      )
   }
}

as you can see I create rectangle shape with given width and height but I don't have any idea how to generate rounded corners.

I dont know about d3 is it possible to do this with either d3?

Upvotes: 2

Views: 4703

Answers (1)

Kamaal ABOOTHALIB
Kamaal ABOOTHALIB

Reputation: 3548

You can use ART Path object to create paths along with paths curve or curveTo methods or arc arcTo methods. Please check the example Rect component below.

import React from 'react'
import PropTypes from 'prop-types'
import {ART} from 'react-native'
const {Group, Shape, Path} = ART

function Rect({fill, stroke, x, width, y, rc, height, topLeftRadius, topRightRadius, bottomRightRadius, bottomLeftRadius, ...rest}){
    const startX = 0;
    const startY = 0;
    const smallDimension = width > height ? height : width;
    let tlr = topLeftRadius !== null ? topLeftRadius : rc; tlr =  tlr > smallDimension/2 ? smallDimension /2 : tlr;
    let trr = topRightRadius !== null ? topRightRadius : rc; trr = trr > smallDimension/2 ? smallDimension /2 : trr;
    let brr = bottomRightRadius !== null ? bottomRightRadius : rc; brr = brr > smallDimension/2 ? smallDimension /2 : brr;
    let blr = bottomLeftRadius !== null ? bottomLeftRadius : rc; blr = blr > smallDimension/2 ? smallDimension /2 : blr;
    const d = Path()
                .move(startX, startY)
                .move(startX, tlr)
                .arc( tlr, startY-tlr, tlr, tlr, false, false) // top left
                .lineTo(width - trr, startY)
                .arc( trr, startX+trr, trr, trr, false, false) // top right
                .lineTo(width, startY+ (height - brr))
                .arc(startX-brr, brr, brr, brr, false, false) // bottom right
                .lineTo(startX + blr, height)
                .arc(startX-blr, startY-blr, blr, blr, false, false) // bottom right
                .close()

    return(
        <Group x={x} y={y}>
            <Shape {...rest} fill={fill} stroke={stroke} d={d}/>
        </Group>
    )
}

Rect.propTypes = {
    width: PropTypes.number.isRequired,
    height: PropTypes.number.isRequired,
    x: PropTypes.number,
    y: PropTypes.number,
    fill: PropTypes.string,
    stroke: PropTypes.string,
    topLeftRadius: PropTypes.number,
    topRightRadius: PropTypes.number,
    bottomRightRadius: PropTypes.number,
    bottomLeftRadius: PropTypes.number,
    rc: PropTypes.number
}

Rect.defaultProps = {
    x: 0,
    y: 0,
    fill: 'transparent',
    stroke: 'red',
    topLeftRadius: null,
    topRightRadius: null,
    bottomRightRadius: null,
    bottomLeftRadius: null,
    rc: 0
}

export default Rect

Here you have completely scalable independent rounded-corner support rectangle component.

  • Props width & height - will normal rect no rounded corner at all.
  • Props width, height & rc - will give you equal rounded of all corner.
  • Props width, height & topRightRadius (or any other corner) - will give you each given rouned corner.

Please check this gist for complete usage.enter image description here

Upvotes: 2

Related Questions