I have a image and svg rect as overlay. when i try the react-image-magnifiyer and it working normally. but when i try to overlay with svg the magnifier didn't work. please guide me how to create magnifier on image hover with svg rect as overlay
JSX:
<div class="img-overlay-wrap" style={{ marginLeft: "27%" }}>
<img src={object.base64} style={{ height:`512` , width:`512`}} alt="" />
<svg style={{ display: (this.state.isHide ? 'block' : 'none') }} width="512" height="512" >
{
object.bbox.map((val,index)=>
<g>
<rect x={object.bbox[index][0]} y={object.bbox[index][1]} width={object.bbox[index][2]} height={object.bbox[index][3] }
style={{stroke:"red",paddingTop:"50px",strokeWidthTop:"20px"}} fill-opacity="0.0" />
</g>
)
}
</svg>
</div>
my attempt:
<div class="img-overlay-wrap" style={{ marginLeft: "27%" }}>
<GlassMagnifier className='img-overlay-wraps' imageSrc={object.name} />
<svg style={{ display: (this.state.isHide ? 'block' : 'none') }} width="512" height="512" >
{
object.bbox.map((val,index)=>
<g>
<rect x={object.bbox[index][0]} y={object.bbox[index][1]} width={object.bbox[index][2]} height={object.bbox[index][3] }
style={{stroke:"red",paddingTop:"50px",strokeWidthTop:"20px"}} fill-opacity="0.0" />
</g>
)
}
</svg>
</div>
This is the element I'm trying to apply the spin anim to:
<svg xmlns="http://www.w3.org/2000/svg" className="h-6 w-6 inline hover:animate-spin" fill="none" viewBox="0 0 24 24" stroke="currentColor" >
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} ... />
</svg>
As I hover over the element nothing happens. If I remove the hover pseudo class it works.
You have to generate hover variant. As the documentation says:
By default, only responsive variants are generated for animation utilities.
You can control which variants are generated for the animation utilities by modifying the animation property in the variants section of your tailwind.config.js file.
For example, this config will also generate hover and focus variants:
// tailwind.config.js
module.exports = {
variants: {
extend: {
// ...
animation: ['hover', 'focus'],
}
}
}
I have built a fade carousel which also requires to change the color of an inline svg on top of it (an overlay decoration, basically). The expected result should be similar to this:
I tried several ways to achive this kind of fade transition using transition: fill 0.2s ease, animation and keyframes but it doesn't work. Instead of transitioning, it just changed the color instantly.
I defined the linear gradient inside the SVG and use something like this fill: url(#primary) to fill: url(#blue) to change the color for every classes because I couldn't find a way to apply gradient inside the path via CSS.
I'm wondering what is the proper way to do this..
hero-overlay.svg
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="728.844" height="1023.046" viewBox="0 0 728.844 1023.046">
<defs>
<linearGradient id="primary" x1="0.226" y1="-0.045" x2="0.544" y2="0.549" gradientUnits="objectBoundingBox">
<stop offset="0" stop-color="#2930fb" stop-opacity="0.7"/>
<stop offset="1" stop-color="#15187e" stop-opacity="0"/>
</linearGradient>
<linearGradient id="blue" x1="0.226" y1="-0.045" x2="0.544" y2="0.549" gradientUnits="objectBoundingBox">
<stop offset="0" stop-color="#54a0ff" stop-opacity="0.7"/>
<stop offset="1" stop-color="#15187e" stop-opacity="0"/>
</linearGradient>
<linearGradient id="purple" x1="0.226" y1="-0.045" x2="0.544" y2="0.549" gradientUnits="objectBoundingBox">
<stop offset="0" stop-color="#5f27cd" stop-opacity="0.7"/>
<stop offset="1" stop-color="#15187e" stop-opacity="0"/>
</linearGradient>
</defs>
<path d="M105.818,23.9c219.16-2.006,219.411-2.257,298.9,200.592C447.6,333.316,488.972,442.638,531.851,550.456,582,675.826,632.153,880.8,692.083,1033c82.5-245.223.426,0,0,0-138.417,1.5-251.256,58.55-313.443-72.836-51.907-109.322-93.281-223.659-138.166-335.991C161.235,428.1,83.251,232.017,0,23.9Z" transform="translate(0 -23.551)" fill="url(#a)"/>
</svg>
Vector.vue (svg loaded using #nuxtjs/svg)
<template>
<div class="vector" v-html="source"></div>
</template>
<script>
export default {
props: {
file: {
type: String,
required: true
}
},
computed: {
source() {
const source = require(`~/static/vectors/${this.file}.svg?raw`)
return source
}
}
}
</script>
Hero.vue
<template>
<header class="hero">
<div class="container">
<div class="content">
<div class="textbox">
<transition name="fade" mode="out-in">
<template v-for="(slide, i) in slides">
<div class="slide-content" :key="slide.id" v-if="current == i">
<h1 class="punchline">
{{ slide.title }}
</h1>
<p class="caption">{{ slide.caption }}</p>
</div>
</template>
</transition>
<NuxtLink class="link" to="/">
<div class="icon-wrapper">
<Icon icon="chevron-right" />
</div>
</NuxtLink>
</div>
<div class="indicator">
<span
v-for="(slide, i) in slides"
:key="slide.id"
:class="{ active: current == i }"
class="item"
#click="jump(i)"
/>
</div>
</div>
</div>
<!-- this is the overlay -->
<Vector class="overlay" :class="color" file="hero-overlay" />
</header>
</template>
<script>
export default {
data() {
return {
current: 0,
slides: [
{
id: 1,
title: 'Slide 001',
caption: 'say something',
},
{
id: 2,
title: 'Slide 002',
caption: 'say something',
},
{
id: 3,
title: 'Slide 003',
caption: 'say something',
},
],
}
},
computed: {
color() {
if (this.current == 1) return 'blue'
if (this.current == 2) return 'purple'
return 'default'
},
},
methods: {
jump(index) {
this.current = index
}
}
}
</script>
<style scoped>
.overlay::v-deep svg path {
transition: fill 1s ease-out;
/* transition: all 1s ease-out; doesn't work either */
}
.overlay.default ::v-deep svg path {
fill: url(#primary);
}
.overlay.blue ::v-deep svg path {
fill: url(#blue);
}
.overlay.purple ::v-deep svg path {
fill: url(#purple);
}
</style>
I found the way to do this, thanks #Robert for pointing out about the use of linearGradient. The solution for this is to use watch and ref property and listen to the new values. I had to refactor the script a little bit and removed the .blue, .purple, .primary class from the css.
The final script looks like this:
hero-overlay.svg (simplified, it now only use 1 <linearGradient>)
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="728.844" height="1023.046" viewBox="0 0 728.844 1023.046">
<defs>
<linearGradient id="a" x1="0.226" y1="-0.045" x2="0.544" y2="0.549" gradientUnits="objectBoundingBox">
<stop offset="0" stop-color="#2930fb" stop-opacity="0.7"/>
<stop offset="1" stop-color="#15187e" stop-opacity="0"/>
</linearGradient>
</defs>
<path d="M105.818,23.9c219.16-2.006,219.411-2.257,298.9,200.592C447.6,333.316,488.972,442.638,531.851,550.456,582,675.826,632.153,880.8,692.083,1033c82.5-245.223.426,0,0,0-138.417,1.5-251.256,58.55-313.443-72.836-51.907-109.322-93.281-223.659-138.166-335.991C161.235,428.1,83.251,232.017,0,23.9Z" transform="translate(0 -23.551)" fill="url(#a)"/>
</svg>
Hero.vue
<template>
<!-- The rest stays the same -->
<!-- I added `ref` to this component -->
<Vector ref="overlay" class="overlay" file="hero-overlay" />
</template>
<script>
export default {
// data stays the same
computed: {
// Instead of using plain text 'blue, purple, default',
// we can just use the HEX since it no longer be used
// as a class name.
color() {
if (this.current == 1) return '#54a0ff' // 'blue'
if (this.current == 2) return '#5f27cd' // 'purple'
return '#2930fb' // 'default'
},
},
watch: {
// Then watch the value for changes and use it right
// away. First, we gotta target the first `<stop>`
// since the second one are always transparent
// then set the attribute color to match the current
color(val) {
this.$refs.overlay.$el
.querySelector('linearGradient > stop:nth-of-type(1)')
.setAttribute('stop-color', val)
}
},
// methods stays the same
}
</script>
<style scoped>
/*
The css are simplified to this.
We use `::v-deep` because it was scoped
and vue cannot simply find the element directly.
*/
.overlay ::v-deep linearGradient stop {
transition: all 1s ease-out;
}
</style>
I want to place a couple of planet images inside my background but can't remove the transparent background (the checker's pattern). As can be seen:
current situation
I tried to set the css with: backgroundColor: "rgba(0,0,0,0)" as can be seen:
const MainScreen = (props) => {
return (
<ImageBackground style={styles.backgroundContainer} source={bgImage}>
<View>
<Image
source={require("../assets/images/red_planet.png")}
style={styles.image}
/>
<TouchableOpacity
style={styles.btnLogin}
onPress={() => props.navigation.navigate("sounds")}
>
<Text style={styles.btnText}>SOUNDS</Text>
</TouchableOpacity>
</View>
</ImageBackground>
);
};
const styles = StyleSheet.create({
image: {
width: 200,
height: 200,
backgroundColor: "rgba(0,0,0,0)",
}
UPDATE: both the image and the background image are .png:
code snipet
Is this something I have to do with photoshop or it can be done with CSS?
Thanks ahead.
This is how I'm showing my image in React-Native:
<View>
<Text style={styles.myTitle}> This is the title 2 </Text>
<Image
style={{ width: null}}
source={require('./images/05.jpg')}
resizeMode="stretch"
/>
</View>
With the resizeMode="stretch" The Image is shown like this:
The same image when displayed with resizeMode="contain" :
<View>
<Text style={styles.myTitle}> This is the title 3</Text>
<Image
style={{ width: null}}
source={require('./images/05.jpg')}
resizeMode="contain"
/>
</View>
resizeMode="contain":
I want the image to be displayed like how it is in the second type, but there are unnecessary margins:
The margins in the first image are perfect but the full image is not shown. I always thought contain will take care of that but it's not helping here. All I want is the entire image to be shown without any extra margins.
Please help. Thanks.
You can use cover, but it will crop part of the image.
To make it work you will need to add a height property to your image:
<View>
<Text>This is the title 3</Text>
<Image
style={{ width: null, height: '100%' }}
source={require('./image.png')}
resizeMode="cover"
/>
</View>