放大时不在屏幕上的SVG部分在缩小时会消失

时间:2018-06-21 18:36:21

标签: css svg css-transitions

我正在使用css过渡来动画缩放SVG。唯一的问题是,当缩小时,SVG的一部分会丢失,直到动画完成,然后全部弹出。

(到目前为止,仅在Mac上的Chrome中经过测试)

svg zoom out pop in

我根本不更改SVG,只是通过在SVG中的组上设置scale transform来放大然后退出。

如何使浏览器重新渲染这些屏幕外元素,以免这样弹出?

const root = document.getElementById('root')

setTimeout(function() {
  root.setAttribute('transform', 'scale(10,10)')
}, 1)

setTimeout(function() {
  root.setAttribute('transform', 'scale(1,1)')
}, 4200)
#root {
  transition: 4s transform;
}

circle {
  stroke: white;
  stroke-width: 3px;
}
<svg viewbox="0 0 300 100">
  <g id="root">
    <circle cx="50" cy="50" r="50" />
    <circle cx="100" cy="50" r="50" />
    <circle cx="150" cy="50" r="50" />
    <circle cx="200" cy="50" r="50" />
    <circle cx="250" cy="50" r="50" />
  </g>
</svg>

4 个答案:

答案 0 :(得分:1)

怎么样,过渡每个圈子, 这样可以吗?

我实际上没有解释为什么它如此工作

const circles = document.getElementsByTagName('circle')

setTimeout(function() {
  circles[0].setAttribute('transform', 'scale(10,10)');
  circles[1].setAttribute('transform', 'scale(10,10)');
  circles[2].setAttribute('transform', 'scale(10,10)');
  circles[3].setAttribute('transform', 'scale(10,10)');
  circles[4].setAttribute('transform', 'scale(10,10)');
}, 1)

setTimeout(function() {
   circles[0].setAttribute('transform', 'scale(1,1)');
   circles[1].setAttribute('transform', 'scale(1,1)');
   circles[2].setAttribute('transform', 'scale(1,1)');
   circles[3].setAttribute('transform', 'scale(1,1)');
   circles[4].setAttribute('transform', 'scale(1,1)');
}, 4200)
#root {
  transition: 4s transform;
}

circle {
 stroke: white;
 stroke-width: 3px;
 transition: 4s transform;
}
<svg viewbox="0 0 300 100">
 <g id="root">
   <circle cx="50" cy="50" r="50" />
   <circle cx="100" cy="50" r="50" />
   <circle cx="150" cy="50" r="50" />
   <circle cx="200" cy="50" r="50" />
   <circle cx="250" cy="50" r="50" />
 </g>
</svg>

答案 1 :(得分:1)

为什么不过渡整个svg元素?

const root = document.getElementById('root')

setTimeout(function() {
  root.setAttribute('transform', 'scale(10,10)')
}, 1)

setTimeout(function() {
  root.setAttribute('transform', 'scale(1,1)')
}, 4200)
#root {
  transition: 4s transform;
  transform-origin: top left;
}

circle {
  stroke: white;
  stroke-width: 3px;
}
<svg id="root" viewbox="0 0 300 100">
  <g>
    <circle cx="50" cy="50" r="50" />
    <circle cx="100" cy="50" r="50" />
    <circle cx="150" cy="50" r="50" />
    <circle cx="200" cy="50" r="50" />
    <circle cx="250" cy="50" r="50" />
  </g>
</svg>

答案 2 :(得分:1)

正如评论中所说,这可能是由于CSS渲染器中的一些优化。
这是一个Chrome错误(他们的CSS绘画优化中有很多...),您应该let them know about it

目前,您是否考虑过使用SMIL?

由于您在代码中使用了javascript,因此我假设您是在允许脚本执行的某个位置(即,不在transform标签中)运行的浏览器中运行此脚本,因此您将能够使用FakeSmile之类的polyfill。
因此,与通过CSS过渡(IIRC IE <11不支持svg元素上的CSS变换过渡)相比,这实际上将为您提供更好的浏览器支持,而且比仍处于试验阶段的仅SVG2混合 SVGTransformAttribute < / em>。 确实,目前只有Chrome支持支持(可能是因为某些属性在SVG1.1中已经可以CSS转换了,// and if you need JS control document.onclick = e => { document.getElementById('zoomin').beginElement(); };的语法与CSS等效,但算法应该有所不同) )。

以下是您在SMIL中的示例:

circle {
  stroke: white;
  stroke-width: 3px;
  transform: translateZ(1);
}
<svg viewbox="0 0 300 100">
  <g id="root">
    <animateTransform attributeName="transform" type="scale" id="zoomin"
      from="1 1" to="10 10" dur="4s" begin="1s"/>
    <animateTransform attributeName="transform" type="scale" id="zoomout"
      from="10 10" to="1 1" dur="4s" begin="zoomin.end"/>    
    <circle cx="50" cy="50" r="50" />
    <circle cx="100" cy="50" r="50" />
    <circle cx="150" cy="50" r="50" />
    <circle cx="200" cy="50" r="50" />
    <circle cx="250" cy="50" r="50" />
  </g>
  <!-- for IE -->
  <script xlink:href="https://cdn.rawgit.com/FakeSmile/FakeSmile/master/smil.user.js"></script>
</svg>
extern crate reqwest;

use std::io::Read;

pub fn main() {
    let mut response = reqwest::get("https://api.fcoin.com/v2/market/ticker/ftbtc")
        .expect("Failed to send request");
    let mut buf = String::new();
    response
        .read_to_string(&mut buf)
        .expect("Failed to read response");
    println!("{}", buf);
}

答案 3 :(得分:0)

setAttribute需要style属性。试试这个脚本:

setTimeout(function() {
 root.setAttribute('style', 'transform: scale(10,10)')
}, 1)

setTimeout(function() { 
    root.setAttribute('style', 'transform: scale(1,1)')
}, 4200)