2012-05-31 1 views
2

다이어그램 작성 응용 프로그램에서 SVG 도면을 표시하는 데 문제가 있습니다. 캔버스는 포함 된 문서 대신 상위 구성 요소의 크기를 사용합니다. 이 크기보다 큰 문서는 완전히 렌더링되지 않습니다.JSVGScrollPane 내의 JSVGCanvas를 SVGDocument 크기와 일치 시키십시오.

케이스

I는, 예를 들면 621x621 화소 도면있다.

<?xml version="1.0" encoding="UTF-8"?> 
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" contentScriptType="text/ecmascript" zoomAndPan="magnify" contentStyleType="text/css" preserveAspectRatio="xMaxYMax slice" version="1.0"> 
    <rect x="50" y="50" fill="white" width="20" height="20" stroke="black" stroke-width="1"/> 
    <rect x="600" y="600" fill="blue" width="20" height="20" stroke="black" stroke-width="1"/> 
</svg> 

동적으로 생성되므로 viewBox가 없습니다. 문서를 만들 때 크기가 없습니다.

JSVGCanvas 안에 JSVGScrollPane이 있고, 스크롤 패널의 부모가 문서보다 작 으면 500x500 픽셀이됩니다. 응용 프로그램을 실행하면

예상되는 동작

500x500에 맞는 도면의 일부를 볼 수 있습니다. 밑에있는 문서가 더 크기 때문에 왼쪽으로 121px 스크롤 할 수있는 스크롤바가 있습니다.

프레임의 크기를 늘리면 점점 더 많은 드로잉이 표시됩니다. 크기를 620x620px보다 크게 늘리면 스크롤 막대가 완전히 사라질 수 있습니다.

패널을 작게 한 다음 문서를 다시 만들면 스크롤 막대가 다시 나타납니다. 응용 프로그램을 실행하면

가 발생했습니다 동작은

500x500에 맞는 도면의 일부를 볼 수 있습니다. 표시되는 스크롤 막대가 없습니다.

패널을 크게 만들면 캔버스가 증가 (배경색)되지만 도면은 초기 500x500px 외부에있는 부분으로 확장되지 않습니다.

패널을 작게 만들 때 400x400으로 말하면 스크롤바가 나타나지만 100px 스크롤 만 허용합니다. 따라서 캔버스는 여전히 원하는 621x621 대신 초기 500x500입니다.

만난 동작은 바틱 저장소와 나는 위에서 추가 한 SVG 파일에 ScrollExample 재현 할 수 있습니다. 이 예에서는 고정 크기 인 500x500 픽셀을 사용합니다.

배경색을 캔버스와 스크롤 패널에 추가하는 경우 전체 프레임이 파란색입니다. 따라서 캔버스의 크기가 커지면 초기 크기를 초과하여 그려지지 않습니다.

canvas.setBackground(Color.blue); 
scroller.setBackground(Color.red); 

패널의 크기를 조정하면 문서를 재설정 할 수 있습니다. 이렇게하면 도면의 보이는 부분을 다시 그릴 수 있지만 캔버스가 여전히 문서 크기가 아닌 보이는 부분의 크기이기 때문에 스크롤이 예상대로 작동하지 않습니다. 이 리스너를 프레임 (또는 내가 생각하는 다른 패널)에 추가하여 테스트 할 수 있습니다.나는이 뷰 박스가 있어야하지만, 내 문서 (A modelchange 이벤트를 기반으로) 자주 다시 내가 문서를 작성하고있을 때, 내가 뷰 박스 얻는 방법을 모르는 읽고

class ResizeListener implements ComponentListener { 

    JSVGCanvas canvas; 
    URI url; 

    public ResizeListener(JSVGCanvas c, URI u) { 
     canvas = c; 
     url = u; 
    } 

    @Override 
    public void componentResized(ComponentEvent arg0) { 
     canvas.setURI(url.toString()); 
     // Calling invalidate on canvas or scroller does not work 
    } 

    // ... 
}; 

. SVGDocument.getRootElement().getBBox();은 보통 null입니다. viewBox가 주어지지 않았을 때 Batik 코드에 대체물이 있어야하기 때문에 이것은 선택 사항입니다. 또한 어딘가에서 이동하면 문서를 변경하면이 이동을 유지해야합니다.

나는 내 문제를 분명히하고 싶습니다. JSVG 클래스가 너무 많아 기대했던 동작을 상자에서 꺼내기를 기대하거나 여기에 뭔가 빠졌습니까? 누군가 나를 해결책으로 이끌 수 있습니까?

답변

1

해결책을 찾은 것 같습니다. 대신 viewBox 난장판의 높이와 너비를 설정해야 망치다. 크기를 설정하면 viewBox가 필요없고 스크롤 막대가 예상대로 작동합니다. 뷰 박스를 설정하면 캔버스가 이미지 크기를 유지하여 이미지를 잘 맞 춥니 다.

이제는 크기를 업데이트하기 위해 크기에 영향을 줄 수있는 dom을 변경할 때마다이 방법을 사용합니다.

static BridgeContext ctx = new BridgeContext(new UserAgentAdapter()); 
static GVTBuilder builder = new GVTBuilder(); 

private static void calculateSize(SVGDocument doc) { 
    GraphicsNode gvtRoot = builder.build(ctx, doc); 

    Rectangle2D rect = gvtRoot.getSensitiveBounds(); 

    doc.getRootElement().setAttributeNS(null, 
      SVGConstants.SVG_WIDTH_ATTRIBUTE, rect.getMaxX() + ""); 
    doc.getRootElement().setAttributeNS(null, 
      SVGConstants.SVG_HEIGHT_ATTRIBUTE, rect.getMaxY() + ""); 
} 

은 내가 UpdateManager 스레드의 외부에서이 을하고 DOM을 수정 후 나는 JSVGCanvas.setSVGDocument()를 사용합니다. UpdateManager을 통해이 작업을 수행하려고 시도했을 때 첫 번째 변경 사항 만 업데이트되었습니다. updatequeue의 올바른 초기화로이 문제를 해결할 수도 있지만, 많은 문서를 변경하기 때문에 매번 새로운 작업을 시작할 수 있습니다.

사소한 문제점이 하나 남았습니다. 새 문서를 설정할 때마다 스크롤 위치가 재설정됩니다. 조작하기 전에 변환을 시도하고 나중에 다시 적용하려고 시도했지만 작동하지 않습니다.

편집 + : 전체 문서를 바꾸는 대신 문서의 루트 노드를 교체하여이 사소한 문제를 해결할 수있었습니다. 캔버스는 문서 상태 ALWAYS_DYNAMIC으로 설정됩니다. 문서의 변경 내용은 루트 노드의 새 크기 (위에서 설명한대로 설정 됨)를 포함하여 즉시 적용됩니다. 그러나 문서가 완전히 대체되지 않기 때문에 스크롤 상태가 유지됩니다.

캔버스는 문서 렌더링이 끝난 후에 만 ​​dom을 수정할 준비가되었습니다. SVGLoad-listener를 사용하여이를 감지했습니다.

class Canvas extends JSVGCanvas implements SVGLoadEventDispatcherListener { 

    public Canvas() { 
     super(); 
     setDocumentState(ALWAYS_DYNAMIC); 
     addSVGLoadEventDispatcherListener(this); 
    } 

    /** 
    * Indicatates whether the canvas has finished its first render, the 
    * canvas is now ready for modification of the dom 
    */ 
    private boolean isReadyForModification = false; 

    /** 
    * Renew the document by replacing the root node with the one of the new 
    * document 
    * 
    * @param doc The new document 
    */ 
    public void renewDocument(final SVGDocument doc) { 

     if (isReadyForModification) { 
      getUpdateManager().getUpdateRunnableQueue().invokeLater(
        new Runnable() { 
         @Override 
         public void run() { 
          // Get the root tags of the documents 
          Node oldRoot = getSVGDocument().getFirstChild(); 
          Node newRoot = doc.getFirstChild(); 

          // Make the new node suitable for the old 
          // document 
          newRoot = getSVGDocument().importNode(newRoot, 
            true); 

          // Replace the nodes 
          getSVGDocument().replaceChild(newRoot, oldRoot); 
         } 
        }); 
     } else { 
      setSVGDocument(doc); 
     } 

    } 

    @Override 
    public void svgLoadEventDispatchCompleted(SVGLoadEventDispatcherEvent e) { 
     isReadyForModification = true; 
    } 

    // ... 
} 
관련 문제