react native svg LinearGradient apply to d3-shape arc seems werid - d3.js

what confuse me is the way that the gradient color apply to arc, it seems not right, seems the colors cut off from special location, because of that the gradient color seems not gradient from start color to end color,
here is the code:
'use strict';
import React, {Component} from 'react'
import {View, StyleSheet} from 'react-native'
import Svg, {Defs, Stop, G, Path, LinearGradient, Line} from 'react-native-svg'
import {arc} from 'd3-shape'
export default class TestPage extends Component {
constructor(props) {
super(props);
}
render() {
let rIn, rOut, rMiddle, startAngle, endAngle;
rIn = 50;//inner circle radius
rOut = 55;//outer circle radius
rMiddle = 52.5;//middle circle radius
startAngle = 0;//start angle 0
endAngle = 300;//end angle 300
let circlePath = arc()
.innerRadius(rIn)
.outerRadius(rOut)
.cornerRadius(rMiddle - rIn)
.startAngle(startAngle)
.endAngle(2 * Math.PI / 360 * endAngle);
return (
<View style={Styles.wrap}>
<View style={{width: 300, height: 200, backgroundColor: '#000000', marginTop: 2}}>
<Svg width={300} height={200}>
<Defs>
<LinearGradient
id={'wholeArcLengthLine'}
x1={0}
y1={0}
x2={(2 * Math.PI * rMiddle * endAngle / 360).toFixed(2)}
y2={0}>
<Stop offset="0" stopColor={"#ff0000"}/>
<Stop offset="0.36" stopColor={"#ef52a3"}/>
<Stop offset="0.7" stopColor={"#b445dd"}/>
<Stop offset="1" stopColor={"#0000ff"}/>
</LinearGradient>
</Defs>
<G>
<Line
x={5}
y={10}
x1={0}
y1={0}
x2={(2 * Math.PI * rMiddle * endAngle / 360).toFixed(2)}
y2={0}
stroke={'url(#wholeArcLengthLine)'}
strokeWidth="5"/>
<Path
x={100}
y={100}
d={circlePath()}
fill={'url(#wholeArcLengthLine)'}/>
</G>
</Svg>
</View>
</View>
)
}
}
const Styles = StyleSheet.create({
wrap: {
flex: 1,
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
},
});
and here is the result, the arc gradient color is different from the Line colr:
so why?
and version:
react: 16.0.0-alpha.12
react-native: 0.45.1
react-native-svg: 5.2.0
d3-shape: 1.2.0

Related

Changing the color of the objects of SVG in D3

I have the below objects in SVG and want to change the color in D3
<svg width=100 height=100>
<circle cx=10 cy=30 r=15></circle>
<circle cx=60 cy=30 r=15></circle>
<rect x=10 y=80 width=60 height=10></rect>
</svg>
I want to make 1st circle as green, 2nd as pink, and rectangle as gold.
One typical d3 (data driven documents) way to do it would be like this:
(Start with the data structure, and drive the DOM from that, using d3)
const myShapes = [
{shape: "circle", cx: 10, cy: 30, r: 15, fill: "green"}, //<circle cx=10 cy=30 r=15 fill='green'></circle>
{shape: "circle", cx: 60, cy: 30, r: 15, fill: "pink"}, //<circle cx=60 cy=30 r=15 fill='pink'></circle>
{shape: "rect", x: 10, y: 80, width: 60, height: 10, fill: "gold"} //<rect x=10 y=80 width=60 height=10 fill='gold'></rect>
];
const svg = d3.select('svg')
svg.selectAll('.shape')
.data(myShapes)
.enter()
//.append('g') //you could surround each element in a group
.append(d => document.createElementNS('http://www.w3.org/2000/svg', d.shape)) //d3.creator(d.shape)
.attr('class', d => d.shape)
.attrs(d => {
//console.log(d)
const copy = {...d}
delete copy.shape
return copy
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js">
</script>
<script src="https://d3js.org/d3-selection-multi.v1.min.js">
</script>
<svg width="100%" viewbox="0 0 200 200">
</svg>
Output:

facing problems with styling on react native and achieving a better responsive layout

I tried to run my code on various screen sized emulators and the layout of my design varies from device to device. I need help to make the layout more responsive and fixed on different sized screens such as tablets, 3"mobile and 6"mobile.
-----------or connect with us on----------- I want to style this line in better way and that remains the same look on every device
I tried using the dimensions of the screen by defining the width and height using variables, and by describing the values in percentages, but nothing worked.
import React, { Component } from 'react';
import { View,TouchableOpacity, Text, StyleSheet, Image, Dimensions } from 'react-native';
import BacgroundImage from './BackgroundImage';
import Buttons from './Reusable/Button';
const { width: WIDTH } = Dimensions.get('window');
class LaunchScreen extends Component {
render() {
return (
<BacgroundImage>
<View style={styles.logoContainer}>
<Image
source={require('./images/logo.png')}
style={styles.PlaceLogo}
/>
</View>
<View style={styles.Buttons}>
<Buttons style={styles.signupButton}
onPress={() => navigate('Login')}>
<Text style={styles.buttonText}> SIGN UP</Text>
</Buttons>
<Buttons style={styles.loginButton}>
<Text style={styles.buttonText}> SIGN IN</Text>
</Buttons>
</View >
<View style={styles.sepratorView}>
<Text style={styles.sepratorText}>--------- or connect with us on ---------</Text>
</View >
<View style={styles.socialButtonStyle}>
<TouchableOpacity
style={styles.fbstyle}
activeOpacity={0.5}
>
<Image
source={require('./images/facebookicon.png')}
style={styles.iconstyle}
/>
<View
style={styles.sepratorLine}
/>
<Text
style={styles.socialButtonText}
>FACEBOOK</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.googlestyle}
onPress={this.signIn}
activeOpacity={0.5}
>
<Image
source={require('./images/google.png')}
style={styles.iconstyle}
/>
<View
style={styles.sepratorLine}
/>
<Text style={styles.socialButtonText} >GOOGLE</Text>
</TouchableOpacity>
</View>
</BacgroundImage>
);
};
}
const styles = StyleSheet.create({
logoContainer: {
flex: 1
},
PlaceLogo: {
width: WIDTH - 140,
margin: 75,
resizeMode: 'center',
justifyContent: 'center',
alignItems: 'center',
},
yosoButtons: {
width: WIDTH - 80,
justifyContent:'center',
marginTop:350
},
signupButton: {
height:40,
paddingTop:7,
marginBottom: 15,
},
loginButton: {
height:40,
paddingTop:7,
marginBottom: 15
},
buttonText: {
},
sepratorText: {
textAlign:'center',
fontSize:20,
color: '#b6b7ba',
},
sepratorView: {
flexDirection: 'row',
justifyContent:'center',
alignItems:'center'
},
socialButtonStyle:{
flex:1,
flexDirection:'row',
justifyContent:'center',
alignItems:'center',
margin:5
},
fbstyle:{
flex:1,
flexDirection:'row',
borderColor:'white',
alignItems:'center',
backgroundColor:'#485a96',
borderWidth:1,
borderRadius:35,
height: 40,
marginLeft:15,
marginRight:15
},
googlestyle:{
flex:1,
flexDirection:'row',
alignItems:'center',
backgroundColor:'#dc4e41',
borderWidth:1,
borderRadius:35,
borderColor:'white',
height: 40,
marginRight:15
},
iconstyle:{
resizeMode:'stretch',
height:25,
width:25
},
sepratorLine:{
backgroundColor:'white',
width:2,
height: 40
},
socialButtonText:{
color: '#fff',
flex:1,
textAlign: 'center',
fontSize: 15,
fontWeight: "bold"
}
});
export default LaunchScreen;
I want the layout to remain the same. Both the logo and buttons remain at the same position on every device display.
And I want a better dynamic solution for separator I have used in code
--------------or connect with us on-----------
I got a workaround solution for this problem. I am assigning values using the height and width of the screen to the styling.
import { StyleSheet, Dimensions } from 'react-native';
const { width: WIDTH, height: HEIGHT } = Dimensions.get('window');
SomeText: {
fontSize: HEIGHT / 38,
marginTop: WIDTH / 20,
}

React Native LayoutAnimation scrollView container size

I have some components wrapped in a ScrollView and for some condition the bottom most component shouldn't render. When that happens, I use LayoutAnimation to hide it. The problem is that when the component disappear, the ScrollView jumps to the new content height directly, without any animation at all.
I want to use LayoutAnimation since I have screens where the contents height is unknown.
Example image
If you look at the image, when the button is pressed, the screen will instantly jump to the blue box without any animation.
state = { showGreenBox: false };
renderBottomBox() {
if (this.state.showGreenBox) {
return (
<View style={{ height: 300, width: 100, backgroundColor: 'green' }} />
);
}
}
render() {
return (
<ScrollView>
<View style={{ height: 300, width: 100, backgroundColor: 'red' }} />
<View style={{ height: 300, width: 100, backgroundColor: 'blue' }} />
{this.renderBottomBox()}
<TouchableOpacity
onPress={() => {
LayoutAnimation.configureNext(LayoutAnimation.Presets.spring);
this.setState({ showGreenBox: !this.state.showGreenBox });
}}
>
<Text>Press to collapse green box</Text>
</TouchableOpacity>
</ScrollView>
);
}

React native - scaling an image clips it instead

I have an image for my app, and it should cover the entire screen. It's a bit wide and tall, so I want to rescale it to fit the screen (never mind aspect ratio at the moment). However, the width and height I apply don't rescale the image, but rather clip it.
Here's my code:
render() {
const width = Dimensions.get('window').width;
const height = Dimensions.get('window').height;
const imageWidth = { width: width };
return (
<View style={styles.container}>
<Image
style={styles.openingImage, imageWidth}
source={require('./src/images/opening.jpg')}>
</Image>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
backgroundColor: '#ff0000',
},
openingImage: {
resizeMode: 'cover',
}
});
Why is it cliping instead of resizing?
Set both width and height of the Image to undefined
imageStyle: {
width: undefined,
height: undefined,
}

Placing GIF file in HTML5 canvas lose animation

I am trying to place .gif file(with anmation let say helicopter),I am able to place it in canvas but the rotating blades doesnt work.
Let me know what am I missing.
jsfiddle: jsfiddle.net/sajesh1985/ptsdvbrt/
Thanks
Sajesh
Your fiddle is showing use of a gif, but in either case:
A SVG file with a SMIL animation can be driven directly by the browser when the SVG is part of the DOM.
When you use drawImage() with SVG as a source the SVG will need to be rasterized, and when that happens the animations are ignored and the SVG is drawn in its initial position. When drawn the rasterized pixels are blended in with whatever other pixels already exists - there is no separation as canvas is just a bitmap.
The same applies to gif files, only the first frame is taken into consideration.
The solution is to prepare a sprite-sheet which contains the frames you want to animate. Draw a frame from it at the desired interval.
var isvg = document.getElementById("svg").outerHTML;
var c = document.getElementById("canvas");
var ctx = c.getContext("2d");
var svg = new Blob([isvg], {type: "image/svg+xml;charset=utf-8"});
var url = URL.createObjectURL(svg);
var img = new Image();
img.onload = draw;
img.src = url;
// this will always draw the SVG in initial position
function draw() {
setInterval(function() {
ctx.drawImage(img, 0, 0)
}, 33);
}
canvas {border: 1px solid #000}
<canvas id=canvas width=300 height=100></canvas><br>
<svg id="svg" xmlns="http://www.w3.org/2000/svg" width="300px" height="100px">
<rect x="0" y="0" width="300" height="100" stroke="black" stroke-width="1" />
<circle cx="0" cy="50" r="15" fill="blue" stroke="black" stroke-width="1">
<animateMotion path="M 0 0 H 300 Z" dur="3s" repeatCount="indefinite" />
</circle>
</svg>

Resources