imgタグのsrcに、外部リソースのリンクや、インラインイメージを使う必要があり、
Wicketでどう書くのかを調べてみました。
org.apache.wicket.markup.html.image パッケージ配下のクラス
名称 | 説明 |
---|---|
ContextImage.java | コンテキストルートからの相対パスで、画像パスを与えて動作するコンポーネント |
ContextPathGenerator.java | ContextImage.javaで使用しているfileパス生成クラス |
ExternalImage.java | 外部サイトの画像パスを与えて動作するコンポーネント |
ExternalSource.java | sourceタグ向けのコンポーネント |
Image.java | 画像パスとしてResourceReferenceを与えて、動作するコンポーネント |
InlineImage.java | 画像をインライン表示するコンポーネント |
NonCachingImage.java | Image.javaの継承クラス画像パスにパラメータを付与してキャッシュされないようにする |
Picture.java | Image.javaの継承クラス Pictureタグ向け |
Source.java | |
package.html | パッケージHTML |
imgタグで外部リソースと、インラインイメージを使うので、
ExternalImage.java
と、 InlineImage.java
を使えそうです。
ExternalImage.java を使う
使用前のコード
そもそも、ExternalImageの存在を知らず、以下のようなコードで、
AttributeModifier.replace("src", sourceUrl)
を使って、
画像のリンクを書き換えていました。
※これはこれで、動作は問題ありませんでした。
- HTML抜粋
<div class="row voffset10">
<div class="col-md-3 image-box">
<div class="overlay-container">
<img alt="Artist image" class="fit" style="">
<a class="overlay">
<i class="fa fa-search-plus"></i>
<span>Artist Name</span>
</a>
</div>
</div>
</div>
- JAVAコードの抜粋
// Get Festival Id
List objects = getObjects();
IDataProvider dataProvider = new ListDataProvider(objects);
GridView gridView = new GridView("artistContainers", dataProvider) {
private static final long serialVersionUID = 8042417654748558983L;
@Override
protected void populateEmptyItem(Item item) {
item.setVisible(false);
}
@Override
protected void populateItem(Item item) {
DataObject itemObject = item.getObject();
//do something...
//画像パスの取得
Document doc = coll.findOneCCImageByEchonestId(itemObject.getId());
String sourceUrl = doc.getString("url");
// new WebComponent
WebComponent webComponent = new WebComponent("artistImage");
webComponent.add(AttributeModifier.replace("src", sourceUrl));
item.add(webComponent);
}
};
gridView.setColumns(4);
使用後のコード
HTMLに変更はありません。JAVA側の記述を以下の通り変更しました。
ExternalImage image = new ExternalImage("artistImage", sourceUrl);
で、
sourceUrl に画像パスを設定することができます。
// Get Festival Id
List objects = getObjects();
IDataProvider dataProvider = new ListDataProvider(objects);
GridView gridView = new GridView("artistContainers", dataProvider) {
private static final long serialVersionUID = 8042417654748558983L;
@Override
protected void populateEmptyItem(Item item) {
item.setVisible(false);
}
@Override
protected void populateItem(Item item) {
DataObject itemObject = item.getObject();
//do something...
//画像パスの取得
Document doc = coll.findOneCCImageByEchonestId(itemObject.getId());
String sourceUrl = doc.getString("url");
// new ExternalImage
ExternalImage image = new ExternalImage("artistImage", sourceUrl);
item.add(image);
}
};
gridView.setColumns(4);
InlineImage.javaを使う
使用前のコード
HTML記述は同じです。 inlineイメージの場合も、
AttributeModifier.replace("src", sourceUrl)
を使って、
画像のリンクを記述できます。
- HTML抜粋
<div class="row voffset10">
<div class="col-md-3 image-box">
<div class="overlay-container">
<img alt="Artist image" class="fit" style="">
<a class="overlay">
<i class="fa fa-search-plus"></i>
<span>Artist Name</span>
</a>
</div>
</div>
</div>
- JAVA記述
データURIスキーム文字列を作成し、
AttributeModifier.replace("src", sb.toString())
で設定します。
@Override
protected void populateItem(Item item) {
DataObject itemObject = item.getObject();
//do something...
//画像パスの取得
Document doc = coll.findOneByMbid(itemObject.getMbid());
Binary binary = doc.get(Keys.IMAGE_BINARY, Binary.class);
// バイト配列→BASE64へ変換する
Base64.Encoder encoder = Base64.getEncoder();
byte[] encoded = encoder.encode(binary.getData());
String base64Image = new String(encoded);
WebComponent webComponent = new WebComponent("artistImage");
// データURIスキームとして文字列を作成
StrBuilder sb = new StrBuilder();
sb.append("data:data:image/png;base64,");
sb.append(base64Image);
webComponent.add(AttributeModifier.replace("src", sb.toString()));
item.add(webComponent);
}
使用後のコード
InlineImage.javaは、コンストラクタ引数で、
PackageResourceReferenceを求める実装になっており、
byte配列から、PackageResourceReferenceに変換する術が分からなかったので、
InlineImage.javaを参考に、同名のbyte配列をInlineイメージにするコンポーネントを作成してみました。
- InlineImage.java
package xyz.monotalk.festivals4partypeople.web.wicket.markup.html.image;
import com.google.common.base.Strings;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.html.WebComponent;
import org.apache.wicket.util.lang.Args;
import java.util.Base64;
/**
* InlineImage
*/
public class InlineImage extends WebComponent {
byte[] binaryImage;
String contentType;
/**
* Creates an inline image
*
* @param id
* @param binaryImage
*/
public InlineImage(String id, byte[] binaryImage) {
this(id, null, binaryImage);
}
/**
* Creates an inline image
*
* @param id
* @param contentType
* @param binaryImage
*/
public InlineImage(String id, String contentType, byte[] binaryImage) {
super(id);
if (Strings.isNullOrEmpty(contentType)) {
this.contentType = "image/octet-stream";
} else {
this.contentType = contentType;
}
Args.notNull(binaryImage, "binaryImage");
this.binaryImage = binaryImage;
}
/**
* Renders the complete image tag with the base64 encoded content.
*/
@Override
protected void onComponentTag(ComponentTag tag) {
super.onComponentTag(tag);
checkComponentTag(tag, "img");
tag.put("src", createBase64EncodedImage(contentType, binaryImage));
}
/**
* createBase64EncodedImage
*
* @param contentType
* @param binaryImage
* @return
*/
private CharSequence createBase64EncodedImage(String contentType, byte[] binaryImage) {
String base64EncodedImage = Base64.getEncoder().encodeToString(binaryImage);
return "data:" + contentType + ";base64," + base64EncodedImage;
}
}
- JAVA記述
@Override
protected void populateItem(Item item) {
DataObject itemObject = item.getObject();
//do something...
//画像パスの取得
Document doc = coll.findOneByMbid(itemObject.getMbid());
Binary binary = doc.get(Keys.IMAGE_BINARY, Binary.class);
InlineImage inlineImage = new InlineImage("artistImage", "image/png", binary.getData());
item.add(inlineImage);;
}
描画されるHTMLは、以下のようになります。
<div class="col-md-3 image-box">
<div class="overlay-container">
<img alt="Artist image" class="fit" src="data:image/png;base64,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" style="">
</div>
</div>
その他 Image.java を使う
Image.java を使用すると、以下のように記述できます。
ByteArrayResource で設定した画像には、URLが割り当てられ、その画像に対するリンクが、
設定されます。
※なので、Inline画像にはなりません。
@Override
protected void populateItem(Item item) {
DataObject itemObject = item.getObject();
//do something...
//画像パスの取得
Document doc = coll.findOneByMbid(itemObject.getMbid());
Binary binary = doc.get(Keys.IMAGE_BINARY, Binary.class);
//Image Classを使用して、Binaryデータを設定する
Image image = new Image("artistImage", new ByteArrayResource("image/png", binary.getData()));
item.add(image);
}
画像関連のクラスで画像を設定すると、何が嬉しいか?
WebComponent、AttributeModifier#replace() の利用でも、
img タグのscr属性の設定は可能ですが、
Image関連のクラスを利用することで、
設定対象のタグ妥当性チェックがかかるところが嬉しいことなのかと思います。
実装時の記述ミスに画面レンダリングの前に気がつけるのかと。
あとは、実装上1行少なくて済む?
以上です。
コメント