特にインラインのsvg
Angularみたいなどんな要素でもコンポーネント化できる環境だと(最終的なソースのでかさ以外は)何も気にせずsvgの内部をTSでいじり倒せるし
(canvasでええやんってのは置いておきます)
batik自体はまあ、今更感はある気がしますが、試してみます
まずは依存関係 pom.xml
<dependency> <groupId>org.apache.xmlgraphics</groupId> <artifactId>batik-transcoder</artifactId> <version>1.9.1</version> </dependency> <dependency> <groupId>org.apache.xmlgraphics</groupId> <artifactId>batik-codec</artifactId> <version>1.9.1</version> </dependency>
svgの文字列を読み込む場合
val svgStr = ... val doc = SAXSVGDocumentFactory(XMLResourceDescriptor.getXMLParserClassName()) .createDocument(SVGDOMImplementation.SVG_NAMESPACE_URI, StringReader(svgStr))
createDocumentの第2引数がReaderやInputStreamを読み込めるので、
svgのファイルを読み込む場合
val doc = File("image.svg").inputStream().use { SAXSVGDocumentFactory(XMLResourceDescriptor.getXMLParserClassName()) .createDocument(SVGDOMImplementation.SVG_NAMESPACE_URI, it) }
生成されるのはorg.w3c.dom.Documentなので、
DOM操作は容易かと
val svgStr = ... val doc = SAXSVGDocumentFactory(XMLResourceDescriptor.getXMLParserClassName()) .createDocument(SVGDOMImplementation.SVG_NAMESPACE_URI, StringReader(svgStr)).apply { getElementById("title").textContent = "タイトル" }
読み込んだsvgをネストしたい場合
はcloneして追加して適用するval svgStr = ... val doc = SAXSVGDocumentFactory(XMLResourceDescriptor.getXMLParserClassName()) .createDocument(SVGDOMImplementation.SVG_NAMESPACE_URI, StringReader(svgStr)).apply { val svg2Str = ... val clone = SAXSVGDocumentFactory(XMLResourceDescriptor.getXMLParserClassName()) .createDocument(SVGDOMImplementation.SVG_NAMESPACE_URI, StringReader(svg2Str)) .documentElement .cloneNode(true) adoptNode(clone) documentElement.appendChild(clone) }
pngにはき出すには
TranscoderInputとTranscoderOutputをPNGTranscoderに与えます例ではTranscodeする際に、画像サイズを指定
val transOut = ByteArrayOutputStream() PNGTranscoder().apply { val rect = Rectangle(0, 0, 500, 500) addTranscodingHint(PNGTranscoder.KEY_WIDTH, rect.width.toFloat()) addTranscodingHint(PNGTranscoder.KEY_HEIGHT, rect.height.toFloat()) transcode(TranscoderInput(doc), TranscoderOutput(transOut)) }
TranscoderOutputはWriterやOutputStreamを受け取るので、
ファイル出力するなら以下のような感じ
File("image.png").outputStream().use { PNGTranscoder().apply { val rect = Rectangle(0, 0, 500, 500) addTranscodingHint(PNGTranscoder.KEY_WIDTH, rect.width.toFloat()) addTranscodingHint(PNGTranscoder.KEY_HEIGHT, rect.height.toFloat()) transcode(TranscoderInput(doc), TranscoderOutput(it)) } }
ちなみに
Transcodeではなく出来上がったsvgをStringでほしいなら
batikは関係なくて、普通にjavax.xml周りを使って以下とかval xmlStr = StringWriter().use { TransformerFactory.newInstance().newTransformer().apply { setOutputProperty(OutputKeys.INDENT, "yes") setOutputProperty(OutputKeys.METHOD, "xml") setOutputProperty("{http://xml.apache.org/xalan}indent-amount", "2") transform(DOMSource(doc), StreamResult(it)) } it.toString() }
便利な世の中ですねぇ~
いじょ