特にインラインの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()
}
便利な世の中ですねぇ~
いじょ