Icons (Experimental)
mapconductor-icons モジュールは、プログラムによるスタイリングが可能なカスタム描画マーカーアイコンを提供します。この実験的モジュールは、実行時に色、サイズ、その他のプロパティをカスタマイズできるベクタースタイルのアイコンを提供します。
⚠️ 実験的モジュール: このモジュールは実験的であり、将来のバージョンで大幅に変更される可能性があります。本番環境での使用には注意してください。
icons モジュールは、Canvas 描画操作を使用して高品質なマーカーアイコンを作成し、以下を提供します:
- スケーラブルベクターグラフィックス: アイコンはあらゆるサイズで滑らかにスケールします
- 実行時カスタマイズ: 色、サイズ、プロパティを動的に変更できます
- 最適化されたキャッシング: パフォーマンスのための自動ビットマップキャッシング
- 一貫した外観: すべての地図SDKで同じビジュアルスタイル
インストール
Section titled “インストール”build.gradle に icons モジュールを追加します:
dependencies { implementation "com.mapconductor:mapconductor-icons"
// 必須: Bom モジュール implementation "com.mapconductor:mapconductor-bom:$version" // 必須: Core モジュール implementation "com.mapconductor:core"
// 地図SDKを選択 implementation "com.mapconductor:for-googlemaps"}利用可能なアイコン
Section titled “利用可能なアイコン”CircleIcon
Section titled “CircleIcon”カスタマイズ可能な塗りつぶしとストロークを持つシンプルな円形マーカーアイコン:
import com.mapconductor.icons.CircleIcon
// Basic circle iconval basicCircle = CircleIcon()
// Customized circle iconval customCircle = CircleIcon( fillColor = Color.Blue, strokeColor = Color.White, strokeWidth = 2.dp, scale = 1.2f, iconSize = 32.dp)CircleIcon のプロパティ
Section titled “CircleIcon のプロパティ”fillColor: Color: 円の内部色(デフォルト:Color.Red)strokeColor: Color: 境界線の色(デフォルト:Color.White)strokeWidth: Dp: 境界線の太さ(デフォルト: Settings から)scale: Float: サイズ倍率(デフォルト:1.0f)iconSize: Dp: アイコンの基本サイズ(デフォルト: Settings から)debug: Boolean: デバッグアウトラインを表示(デフォルト:false)
FlagIcon
Section titled “FlagIcon”ポールとカスタマイズ可能なフラグを持つフラグスタイルのマーカーアイコン:
import com.mapconductor.icons.FlagIcon
// Basic flag iconval basicFlag = FlagIcon()
// Customized flag iconval customFlag = FlagIcon( fillColor = Color.Green, strokeColor = Color.Black, strokeWidth = 1.5.dp, scale = 1.0f, iconSize = 40.dp)FlagIcon のプロパティ
Section titled “FlagIcon のプロパティ”fillColor: Color: フラグとポールの色(デフォルト:Color.Red)strokeColor: Color: アウトラインの色(デフォルト:Color.White)strokeWidth: Dp: アウトラインの太さ(デフォルト: Settings から)scale: Float: サイズ倍率(デフォルト:1.0f)iconSize: Dp: アイコンの基本サイズ(デフォルト: Settings から)debug: Boolean: デバッグアウトラインを表示(デフォルト:false)
基本的な使用方法
Section titled “基本的な使用方法”シンプルなアイコン使用
Section titled “シンプルなアイコン使用”@Composablefun BasicIconExample() { val circleIcon = CircleIcon( fillColor = Color.Blue, strokeColor = Color.White )
val flagIcon = FlagIcon( fillColor = Color.Red, strokeColor = Color.Black )
// GoogleMapView、MapboxMapView などの選択した地図SDKに置き換えてください MapView(state = mapViewState) { Marker( position = GeoPoint.fromLatLong(37.7749, -122.4194), icon = circleIcon )
Marker( position = GeoPoint.fromLatLong(37.7849, -122.4094), icon = flagIcon ) }}動的アイコンカスタマイズ
Section titled “動的アイコンカスタマイズ”@Composablefun DynamicIconExample() { var iconColor by remember { mutableStateOf(Color.Red) } var iconSize by remember { mutableStateOf(32.dp) }
val dynamicIcon = CircleIcon( fillColor = iconColor, strokeColor = Color.White, iconSize = iconSize )
Column { // カラーピッカー Row { Button(onClick = { iconColor = Color.Red }) { Text("Red") } Button(onClick = { iconColor = Color.Blue }) { Text("Blue") } Button(onClick = { iconColor = Color.Green }) { Text("Green") } }
// サイズスライダー Slider( value = iconSize.value, onValueChange = { iconSize = it.dp }, valueRange = 16f..64f ) Text("Size: ${iconSize.value.toInt()}dp")
// GoogleMapView、MapboxMapView などの選択した地図SDKに置き換えてください MapView(state = mapViewState) { Marker( position = GeoPoint.fromLatLong(37.7749, -122.4194), icon = dynamicIcon ) } }}高度な使用方法
Section titled “高度な使用方法”カテゴリベースのアイコン
Section titled “カテゴリベースのアイコン”@Composablefun CategoryIconExample() { data class POI( val name: String, val category: String, val position: GeoPointInterface ) : java.io.Serializable
val pois = listOf( POI("Restaurant", "food", GeoPoint.fromLatLong(37.7749, -122.4194)), POI("Hotel", "lodging", GeoPoint.fromLatLong(37.7849, -122.4094)), POI("Gas Station", "fuel", GeoPoint.fromLatLong(37.7649, -122.4294)) )
fun getIconForCategory(category: String) = when (category) { "food" -> CircleIcon(fillColor = Color.Red, strokeColor = Color.White) "lodging" -> FlagIcon(fillColor = Color.Blue, strokeColor = Color.White) "fuel" -> CircleIcon(fillColor = Color.Yellow, strokeColor = Color.Black) else -> CircleIcon(fillColor = Color.Gray, strokeColor = Color.White) }
// GoogleMapView、MapboxMapView などの選択した地図SDKに置き換えてください MapView(state = mapViewState) { pois.forEach { poi -> Marker( position = poi.position, icon = getIconForCategory(poi.category), extra = poi.name ) } }}アイコンテーマ
Section titled “アイコンテーマ”object IconTheme { data class Theme( val primaryColor: Color, val secondaryColor: Color, val strokeColor: Color, val strokeWidth: Dp ) : java.io.Serializable
val light = Theme( primaryColor = Color(0xFF2196F3), secondaryColor = Color(0xFFFFFFFF), strokeColor = Color(0xFF000000), strokeWidth = 1.dp )
val dark = Theme( primaryColor = Color(0xFF1976D2), secondaryColor = Color(0xFF424242), strokeColor = Color(0xFFFFFFFF), strokeWidth = 1.dp )}@Composablefun ThemedIconExample() { val isDarkTheme = isSystemInDarkTheme() val theme = if (isDarkTheme) IconTheme.dark else IconTheme.light
val themedCircle = CircleIcon( fillColor = theme.primaryColor, strokeColor = theme.strokeColor, strokeWidth = theme.strokeWidth )
val themedFlag = FlagIcon( fillColor = theme.primaryColor, strokeColor = theme.strokeColor, strokeWidth = theme.strokeWidth )
// GoogleMapView、MapboxMapView などの選択した地図SDKに置き換えてください MapView(state = mapViewState) { Marker( position = GeoPoint.fromLatLong(37.7749, -122.4194), icon = themedCircle )
Marker( position = GeoPoint.fromLatLong(37.7849, -122.4094), icon = themedFlag ) }}アイコンアニメーション
Section titled “アイコンアニメーション”@Composablefun AnimatedIconExample() { var scale by remember { mutableStateOf(1.0f) } var color by remember { mutableStateOf(Color.Red) }
// Animate scale LaunchedEffect(Unit) { while (true) { animate( initialValue = 1.0f, targetValue = 1.5f, animationSpec = tween(1000) ) { value, _ -> scale = value }
animate( initialValue = 1.5f, targetValue = 1.0f, animationSpec = tween(1000) ) { value, _ -> scale = value } } }
// Animate color LaunchedEffect(Unit) { val colors = listOf(Color.Red, Color.Blue, Color.Green, Color.Yellow) var index = 0 while (true) { delay(2000) index = (index + 1) % colors.size color = colors[index] } }
val animatedIcon = CircleIcon( fillColor = color, strokeColor = Color.White, scale = scale )
// GoogleMapView、MapboxMapView などの選択した地図SDKに置き換えてください MapView(state = mapViewState) { Marker( position = GeoPoint.fromLatLong(37.7749, -122.4194), icon = animatedIcon ) }}アイコンのプロパティと動作
Section titled “アイコンのプロパティと動作”アンカーポイント
Section titled “アンカーポイント”アイコンには、地理座標に対してどのように配置されるかを決定する特定のアンカーポイントがあります:
// CircleIcon: anchored at left-center (0.0, 0.5)// FlagIcon: anchored near the base of the pole (0.176, 0.91)情報ウィンドウアンカー
Section titled “情報ウィンドウアンカー”情報ウィンドウ(地図SDKがサポートしている場合)は異なるポイントにアンカーされます:
// CircleIcon info window anchor: center of the circle (0.5, 0.5)// FlagIcon info window anchor: top of the flag (0.5, 0.0)パフォーマンスに関する考慮事項
Section titled “パフォーマンスに関する考慮事項”ビットマップキャッシング
Section titled “ビットマップキャッシング”アイコンは、プロパティハッシュに基づいてレンダリングされたビットマップを自動的にキャッシュします:
// These will share the same cached bitmapval icon1 = CircleIcon(fillColor = Color.Red, strokeColor = Color.White)val icon2 = CircleIcon(fillColor = Color.Red, strokeColor = Color.White)
// This will create a new cached bitmapval icon3 = CircleIcon(fillColor = Color.Blue, strokeColor = Color.White)- キャッシュされたビットマップは自動的に管理されます
- 同一のプロパティを持つアイコンはビットマップインスタンスを共有します
- 大きなアイコンはより多くのメモリを使用します - 適切なサイズを使用してください
アイコンのデバッグ
Section titled “アイコンのデバッグ”デバッグモードを有効にして、アイコンの境界とアンカーポイントを視覚化します:
@Composablefun DebugIconExample() { val debugIcon = CircleIcon( fillColor = Color.Red, strokeColor = Color.White, debug = true // Show debug outline and crosshairs )
// GoogleMapView、MapboxMapView などの選択した地図SDKに置き換えてください MapView(state = mapViewState) { Marker( position = GeoPoint.fromLatLong(37.7749, -122.4194), icon = debugIcon ) }}デバッグモードは以下を表示します:
- アイコンの境界矩形(黒いアウトライン)
- 中心の十字線(黒い線)
- 実際に描画されたコンテンツ
カスタムアイコン開発
Section titled “カスタムアイコン開発”AbstractMarkerIcon の拡張
Section titled “AbstractMarkerIcon の拡張”カスタムアイコンを作成するには、AbstractMarkerIcon を拡張します:
class CustomIcon( private val fillColor: Color = Color.Blue, override val scale: Float = 1.0f, override val iconSize: Dp = 32.dp, override val debug: Boolean = false) : AbstractMarkerIcon() {
override val anchor: Offset = Offset(0.5f, 0.5f) override val infoAnchor: Offset = Offset(0.5f, 0.0f)
override fun toBitmapIcon(): BitmapIcon { val id = "custom_icon_${hashCode()}".hashCode() BitmapIconCache.get(id)?.let { return it }
val canvasSize = ResourceProvider.dpToPx(iconSize.value * scale) val bitmap = createBitmap(canvasSize.toInt(), canvasSize.toInt()) val canvas = Canvas(bitmap)
// Custom drawing code here val paint = Paint().apply { color = fillColor.toArgb() style = Paint.Style.FILL isAntiAlias = true }
canvas.drawRect(0f, 0f, canvasSize.toFloat(), canvasSize.toFloat(), paint)
val result = BitmapIcon( bitmap = bitmap, anchor = anchor, size = Size(canvasSize.toFloat(), canvasSize.toFloat()) ) BitmapIconCache.put(id, result) return result }}ベストプラクティス
Section titled “ベストプラクティス”- 一貫したサイジング: 類似したマーカータイプには一貫したアイコンサイズを使用する
- 色のアクセシビリティ: 塗りつぶしとストロークの色の間に十分なコントラストを確保する
- パフォーマンス: キャッシングの恩恵を受けるために、同一のアイコンインスタンスを再利用する
- 適切なスケール: アイコンサイズを選択する際は、地図のズームレベルを考慮する
- 地図SDK間でのテスト: すべてのターゲット地図SDKでアイコンの外観を確認する
- 限定的なアイコンセット: 現在、CircleIcon と FlagIcon のみが利用可能
- 静的な形状: アイコンはプログラムで描画され、ベクターファイルからではありません
- 地図SDK間の違い: 地図SDK間でわずかなレンダリングの違いが発生する可能性があります
- メモリ使用量: 大きなアイコンや多くのユニークなアイコンバリエーションは、より多くのメモリを消費します
移行と互換性
Section titled “移行と互換性”このモジュールは実験的であり、API が変更される可能性があります。移行時には:
- 特定のユースケースで十分にテストする
- 多数のユニークなアイコンを使用する場合はメモリ使用量を監視する
- 重要な機能にはフォールバックオプションを用意する
- モジュールの改善に役立つように問題を報告する
icons モジュールは、地図SDK間で統一された MapConductor API を維持しながら、カスタムマーカースタイリングの基盤を提供します。