2016-12-12 1 views
9

Ich verwende d3 v4, um SVG-Grafiken zu rendern. Ich verwende ein clipPath auf ein paar <path> Elemente. Ich habe ein Panning-Verhalten für ein Rect-Element und der ClipPath hilft dabei, einige der Pfadelemente zu verbergen. Beim Verschieben in Android. Der ClipPath funktioniert nach Bedarf, aber beim Panning in iOS wird die Zeichnung funky wiedergegeben. Siehe unten:IOS app webview SVG ClipPath Ausgabe

VOR

BEFORE

NACH AFTER PANNING

ich den SVG-Clip mit dem folgenden Code implementiert habe:

this.line = d3.line() 
    .curve(d3.curveMonotoneX) 
    .x((d) => this.xScale(this.getDate(d))) 
    .y((d) => this.yScale(d.kWh)); 

this.area = d3.area() 
    .curve(d3.curveMonotoneX) 
    .x((d) => { 
     return this.xScale(this.getDate(d)) 
    }) 
    .y0(this.height) 
    .y1((d) => this.yScale(d.kWh)); 

// Definition for clipPath 
this.svg.append("defs").append("clipPath") 
    .attr("id", "clip") 
    .append("rect") 
    .attr("width", this.width) 
    .attr('transform', 'translate(0,-20)') 
    .attr("height", this.height + 20); 
// clipPath added to area 
var areaPath = this.focus.append("path") 
    .datum(this.data) 
    .attr("class", "area") 
    .attr('height', this.height) 
    .attr('fill-opacity', .2) 
    .attr('clip-path', 'url(#clip)') 
    .attr("d", this.area) 
    .attr("transform", "translate(0," + 80 + ")") 
    .style("fill", "url(#gradient)"); 
// clipPath added to the line 
var linePath = this.focus.append('path') 
    .datum(this.data) 
    .attr('class', 'line') 
    .attr('fill', 'none') 
    .attr('clip-path', 'url(#clip)') 
    .attr('stroke', '#31B5BB') 
    .attr('stroke-width', '2px') 
    .attr("transform", "translate(0," + 80 + ")") 
    .attr('d', this.line); 

Er ist exce rpt aus dem Zoom, der beim Zoomen aufgerufen wird.

private zoomed =() => { 

     if (this.isMinZooming) return; 

     let diff, 
      domain, 
      minBuffer, 
      maxBuffer, 
      t; 

     t = d3.event.transform; 
     // loose mobile events 
     if (isNaN(t.k)) return; 

     this.xScale.domain(t.rescaleX(this.x2Scale).domain()); 
     diff = this.daydiff(this.xScale.domain()[0], this.xScale.domain()[1]); 

     // Redraw Axis 
     this.xAxis = d3.axisBottom(this.xScale).tickSize(0).tickFormat(d3.timeFormat('%b')); 
     this.focus.select(".axis--x").call(this.xAxis); 

     // Redraw Paths. This is where the redraw function gets messy in the iOS webview. 
     this.focus.select(".area").attr("d", this.area); 
     this.focus.select('.line').attr('d', this.line); 

     ... 
} 

Hat jemand das gleiche Problem, wenn die clipPath mit?

+0

Ich würde sagen, dies liegt an der Tatsache, dass der ClipPath und die Elemente, die Sie schneiden, nicht im selben Koordinatensystem definiert sind und nicht den gleichen Transformationen unterliegen http://StackOverflow.com/a/38088473/1160916 – Ashitaka

+0

@Ashitaka warum würde das für jeden Browser außer IOS funktionieren? Es funktioniert sogar in Safari. Hast du eine Ahnung warum? – inspired

Antwort

0

Ich habe das Problem herausgefunden. Es ist so ein Suddle Bug. Ich war die Definition irgendwo in meiner CSS-Datei:

.area{ 
    clip-path: url(#clip); 
} 

In allen Browsern würde dies für <rect> arbeiten und <path>, aber für die iOS webview würde es die oben Anzeigefehler machen.

definieren, diese stattdessen in einer separaten Datei CSS, ich definierte es inline für all SVG Object, dass ich es als solches gelten wollte:

var areaPath = this.focus.append("path") 
     ... 
     .attr('clip-path', 'url(#clip)') //defining it inline 

Dieser Fehler machte mich verrückt, aber ich bin froh, dass ich‘ Ich habe die Lösung gefunden.