Player marker improvements
- Use <meter> for health/armor - Condense small/body image properties into single image size option - Remove image-size dependant margins - Add circle alongside label for indicating player position
This commit is contained in:
parent
146a5efc82
commit
770c9242a8
@ -48,9 +48,8 @@ export default defineComponent({
|
||||
|
||||
//The player marker
|
||||
marker = new PlayerMarker(props.player, {
|
||||
smallFace: componentSettings.value!.smallFaces,
|
||||
showSkinFace: componentSettings.value!.showSkinFaces,
|
||||
showBody: componentSettings.value!.showBodies,
|
||||
showSkin: componentSettings.value!.showSkins,
|
||||
imageSize: componentSettings.value!.imageSize,
|
||||
showHealth: componentSettings.value!.showHealth,
|
||||
showArmor: componentSettings.value!.showArmor,
|
||||
pane: 'players',
|
||||
|
@ -67,7 +67,7 @@ export default defineComponent({
|
||||
updatePlayerImage = async () => {
|
||||
image.value = defaultImage;
|
||||
|
||||
if(store.state.components.playerMarkers && store.state.components.playerMarkers.showSkinFaces) {
|
||||
if(store.state.components.playerMarkers && store.state.components.playerMarkers.showSkins) {
|
||||
try {
|
||||
const result = await getMinecraftHead(props.target, '16');
|
||||
image.value = result.src;
|
||||
|
@ -91,7 +91,7 @@ export default defineComponent({
|
||||
let image = ref(defaultImage);
|
||||
|
||||
onMounted(() => {
|
||||
if(store.state.components.playerMarkers && store.state.components.playerMarkers.showSkinFaces) {
|
||||
if(store.state.components.playerMarkers && store.state.components.playerMarkers.showSkins) {
|
||||
getMinecraftHead(props.player, '16').then((result) => image.value = result.src).catch(() => {});
|
||||
}
|
||||
});
|
||||
|
7
src/index.d.ts
vendored
7
src/index.d.ts
vendored
@ -320,13 +320,14 @@ interface LiveAtlasPlayerMarkerConfig {
|
||||
hideByDefault: boolean;
|
||||
layerName: string;
|
||||
layerPriority: number;
|
||||
showBodies: boolean;
|
||||
showSkinFaces: boolean;
|
||||
imageSize: LiveAtlasPlayerImageSize;
|
||||
showSkins: boolean;
|
||||
showHealth: boolean;
|
||||
showArmor: boolean;
|
||||
smallFaces: boolean;
|
||||
}
|
||||
|
||||
export type LiveAtlasPlayerImageSize = 'none' | 'small' | 'large' | 'body';
|
||||
|
||||
interface LiveAtlasChatBoxConfig {
|
||||
allowUrlName: boolean;
|
||||
showPlayerFaces: boolean;
|
||||
|
@ -20,7 +20,7 @@
|
||||
import {BaseIconOptions, DomUtil, Icon, Layer, LayerOptions, Util} from 'leaflet';
|
||||
import {getMinecraftHead} from '@/util';
|
||||
import playerImage from '@/assets/images/player_face.png';
|
||||
import {LiveAtlasPlayer} from "@/index";
|
||||
import {LiveAtlasPlayer, LiveAtlasPlayerImageSize} from "@/index";
|
||||
|
||||
const noSkinImage: HTMLImageElement = document.createElement('img');
|
||||
noSkinImage.height = 16;
|
||||
@ -42,9 +42,8 @@ noSkinImage.src = smallImage.src = largeImage.src = bodyImage.src = playerImage;
|
||||
noSkinImage.className = smallImage.className = largeImage.className = bodyImage.className = 'player__icon';
|
||||
|
||||
export interface PlayerIconOptions extends BaseIconOptions {
|
||||
smallFace: boolean,
|
||||
showSkinFace: boolean,
|
||||
showBody: boolean,
|
||||
imageSize: LiveAtlasPlayerImageSize,
|
||||
showSkin: boolean,
|
||||
showHealth: boolean,
|
||||
showArmor: boolean,
|
||||
}
|
||||
@ -60,10 +59,8 @@ export class PlayerIcon extends Layer implements Icon<PlayerIconOptions> {
|
||||
|
||||
private _currentName?: string;
|
||||
|
||||
private _playerHealth?: HTMLDivElement;
|
||||
private _playerHealthBar?: HTMLDivElement;
|
||||
private _playerArmor?: HTMLDivElement;
|
||||
private _playerArmorBar?: HTMLDivElement;
|
||||
private _playerHealth?: HTMLMeterElement;
|
||||
private _playerArmor?: HTMLMeterElement;
|
||||
|
||||
constructor(player: LiveAtlasPlayer, options: PlayerIconOptions) {
|
||||
super(options as LayerOptions);
|
||||
@ -77,7 +74,6 @@ export class PlayerIcon extends Layer implements Icon<PlayerIconOptions> {
|
||||
}
|
||||
|
||||
const player = this._player;
|
||||
let offset = 8;
|
||||
|
||||
this._container = document.createElement('div');
|
||||
|
||||
@ -90,21 +86,23 @@ export class PlayerIcon extends Layer implements Icon<PlayerIconOptions> {
|
||||
this._playerName.className = 'player__name';
|
||||
this._playerName.innerHTML = this._currentName = player.displayName;
|
||||
|
||||
if (this.options.showSkinFace) {
|
||||
if (this.options.showSkin) {
|
||||
let size;
|
||||
|
||||
if (this.options.smallFace) {
|
||||
this._playerImage = smallImage.cloneNode() as HTMLImageElement;
|
||||
size = '16';
|
||||
offset = 8;
|
||||
} else if(this.options.showBody) {
|
||||
this._playerImage = bodyImage.cloneNode() as HTMLImageElement;
|
||||
size = 'body';
|
||||
offset = 16;
|
||||
} else {
|
||||
this._playerImage = largeImage.cloneNode() as HTMLImageElement;
|
||||
size = '32';
|
||||
offset = 16;
|
||||
switch(this.options.imageSize) {
|
||||
case 'small':
|
||||
this._playerImage = smallImage.cloneNode() as HTMLImageElement;
|
||||
size = '16';
|
||||
break;
|
||||
|
||||
case 'body':
|
||||
this._playerImage = bodyImage.cloneNode() as HTMLImageElement;
|
||||
size = 'body';
|
||||
break;
|
||||
|
||||
default:
|
||||
this._playerImage = largeImage.cloneNode() as HTMLImageElement;
|
||||
size = '32';
|
||||
}
|
||||
|
||||
getMinecraftHead(player, size).then(head => {
|
||||
@ -114,37 +112,28 @@ export class PlayerIcon extends Layer implements Icon<PlayerIconOptions> {
|
||||
this._playerImage = noSkinImage.cloneNode(false) as HTMLImageElement;
|
||||
}
|
||||
|
||||
this._container.appendChild(this._playerImage);
|
||||
this._container.appendChild(this._playerInfo);
|
||||
this._playerInfo.appendChild(this._playerImage);
|
||||
this._playerInfo.appendChild(this._playerName);
|
||||
this._container.appendChild(this._playerInfo);
|
||||
|
||||
if (this.options.showHealth) {
|
||||
this._playerHealth = document.createElement('div');
|
||||
this._playerHealth = document.createElement('meter');
|
||||
this._playerHealth.className = 'player__health';
|
||||
this._playerHealth.hidden = true;
|
||||
this._playerHealth.max = 100;
|
||||
|
||||
this._playerHealthBar = document.createElement('div');
|
||||
this._playerHealthBar.className = 'player__health-bar';
|
||||
|
||||
this._playerHealth.appendChild(this._playerHealthBar);
|
||||
this._playerInfo.appendChild(this._playerHealth);
|
||||
}
|
||||
|
||||
if (this.options.showArmor) {
|
||||
this._playerArmor = document.createElement('div');
|
||||
this._playerArmor = document.createElement('meter');
|
||||
this._playerArmor.className = 'player__armor';
|
||||
this._playerArmor.hidden = true;
|
||||
this._playerArmor.max = 100;
|
||||
|
||||
this._playerArmorBar = document.createElement('div');
|
||||
this._playerArmorBar.className = 'player__armor-bar';
|
||||
|
||||
this._playerArmor.appendChild(this._playerArmorBar);
|
||||
this._playerInfo.appendChild(this._playerArmor);
|
||||
}
|
||||
|
||||
this._container.style.marginTop = `-${offset}px`;
|
||||
this._container.style.marginLeft = `-${offset}px`;
|
||||
|
||||
return this._container;
|
||||
}
|
||||
|
||||
@ -165,7 +154,7 @@ export class PlayerIcon extends Layer implements Icon<PlayerIconOptions> {
|
||||
if(this.options.showHealth) {
|
||||
if (this._player.health !== undefined) {
|
||||
this._playerHealth!.hidden = false;
|
||||
this._playerHealthBar!.style.width = Math.ceil(this._player.health * 2.5) + 'px';
|
||||
this._playerHealth!.value = this._player.health * 5;
|
||||
} else {
|
||||
this._playerHealth!.hidden = true;
|
||||
}
|
||||
@ -174,7 +163,7 @@ export class PlayerIcon extends Layer implements Icon<PlayerIconOptions> {
|
||||
if(this.options.showArmor) {
|
||||
if(this._player.armor !== undefined) {
|
||||
this._playerArmor!.hidden = false;
|
||||
this._playerArmorBar!.style.width = Math.ceil(this._player.armor * 2.5) + 'px';
|
||||
this._playerArmor!.value = this._player.armor * 5;
|
||||
} else {
|
||||
this._playerArmor!.hidden = true;
|
||||
}
|
||||
|
@ -16,14 +16,13 @@
|
||||
|
||||
import {LatLng, MarkerOptions, Marker, Map, Util} from 'leaflet';
|
||||
import {PlayerIcon} from "@/leaflet/icon/PlayerIcon";
|
||||
import {LiveAtlasPlayer} from "@/index";
|
||||
import {LiveAtlasPlayer, LiveAtlasPlayerImageSize} from "@/index";
|
||||
import {watch} from "@vue/runtime-core";
|
||||
import {WatchStopHandle} from "vue";
|
||||
|
||||
export interface PlayerMarkerOptions extends MarkerOptions {
|
||||
smallFace: boolean,
|
||||
showSkinFace: boolean,
|
||||
showBody: boolean,
|
||||
showSkin: boolean,
|
||||
imageSize: LiveAtlasPlayerImageSize,
|
||||
showHealth: boolean,
|
||||
showArmor: boolean,
|
||||
}
|
||||
@ -40,9 +39,8 @@ export class PlayerMarker extends Marker {
|
||||
this._player = player;
|
||||
|
||||
this._PlayerIcon = options.icon = new PlayerIcon(player, {
|
||||
smallFace: options.smallFace,
|
||||
showSkinFace: options.showSkinFace,
|
||||
showBody: options.showBody,
|
||||
imageSize: options.imageSize,
|
||||
showSkin: options.showSkin,
|
||||
showHealth: options.showHealth,
|
||||
showArmor: options.showArmor,
|
||||
});
|
||||
|
@ -15,10 +15,18 @@
|
||||
*/
|
||||
|
||||
import {
|
||||
HeadQueueEntry, LiveAtlasArea, LiveAtlasCircle, LiveAtlasComponentConfig,
|
||||
LiveAtlasDimension, LiveAtlasLine, LiveAtlasMarker,
|
||||
LiveAtlasMarkerSet, LiveAtlasPartialComponentConfig,
|
||||
LiveAtlasPlayer, LiveAtlasServerConfig, LiveAtlasServerDefinition,
|
||||
HeadQueueEntry,
|
||||
LiveAtlasArea,
|
||||
LiveAtlasCircle,
|
||||
LiveAtlasComponentConfig,
|
||||
LiveAtlasDimension,
|
||||
LiveAtlasLine,
|
||||
LiveAtlasMarker,
|
||||
LiveAtlasMarkerSet,
|
||||
LiveAtlasPartialComponentConfig,
|
||||
LiveAtlasPlayer,
|
||||
LiveAtlasServerConfig,
|
||||
LiveAtlasServerDefinition,
|
||||
LiveAtlasServerMessageConfig,
|
||||
LiveAtlasWorldDefinition
|
||||
} from "@/index";
|
||||
@ -90,11 +98,10 @@ export default class Pl3xmapMapProvider extends MapProvider {
|
||||
hideByDefault: !!worldResponse.player_tracker?.default_hidden,
|
||||
layerName: worldResponse.player_tracker?.label || '',
|
||||
layerPriority: worldResponse.player_tracker?.priority,
|
||||
showBodies: false,
|
||||
showSkinFaces: true,
|
||||
imageSize: 'small',
|
||||
showSkins: true,
|
||||
showHealth: !!worldResponse.player_tracker?.nameplates?.show_health,
|
||||
showArmor: !!worldResponse.player_tracker?.nameplates?.show_armor,
|
||||
smallFaces: true,
|
||||
}
|
||||
} else {
|
||||
worldConfig.components.playerMarkers = undefined;
|
||||
|
@ -24,28 +24,68 @@
|
||||
|
||||
&.marker--player {
|
||||
transition: transform 0.3s ease-in 0s;
|
||||
height: 1.2rem;
|
||||
margin-left: -0.6rem;
|
||||
margin-top: -0.6rem;
|
||||
|
||||
&:before {
|
||||
content: '';
|
||||
display: block;
|
||||
width: 0.8rem;
|
||||
height: 0.8rem;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
background-color: var(--text-base);
|
||||
border: 0.2rem solid var(--background-dark);
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.marker__label {
|
||||
display: block;
|
||||
display: grid !important;
|
||||
grid-template-columns: min-content 1fr;
|
||||
grid-template-rows: 1fr min-content min-content min-content 1fr;
|
||||
grid-auto-flow: column;
|
||||
column-gap: 0.5rem;
|
||||
margin-left: 1.6rem;
|
||||
background-clip: padding-box;
|
||||
padding-right: 0.5rem;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.player__icon {
|
||||
grid-row: 1 / -1;
|
||||
}
|
||||
|
||||
.player__name {
|
||||
grid-row: 2;
|
||||
}
|
||||
|
||||
.player__health,
|
||||
.player__armor {
|
||||
width: 50px;
|
||||
}
|
||||
width: 5rem;
|
||||
height: 0.7rem;
|
||||
display: block;
|
||||
|
||||
.player__health,
|
||||
.player__armor,
|
||||
.player__health-bar,
|
||||
.player__armor-bar {
|
||||
height: 7px;
|
||||
&::-webkit-meter-inner-element,
|
||||
&::-webkit-meter-bar {
|
||||
border-radius: 0;
|
||||
background: none;
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
image-rendering: crisp-edges;
|
||||
image-rendering: pixelated;
|
||||
}
|
||||
}
|
||||
|
||||
.player__health {
|
||||
background: url(../assets/images/heart_depleted.png) repeat-x left center;
|
||||
}
|
||||
|
||||
.player__health-bar {
|
||||
.player__health::-webkit-meter-optimum-value {
|
||||
background: url(../assets/images/heart.png) repeat-x left center;
|
||||
}
|
||||
|
||||
.player__health::-moz-meter-bar {
|
||||
background: url(../assets/images/heart.png) repeat-x left center;
|
||||
}
|
||||
|
||||
@ -53,7 +93,11 @@
|
||||
background: url(../assets/images/armor_depleted.png) repeat-x left center;
|
||||
}
|
||||
|
||||
.player__armor-bar {
|
||||
.player__armor::-webkit-meter-optimum-value {
|
||||
background: url(../assets/images/armor.png) repeat-x left center;
|
||||
}
|
||||
|
||||
.player__armor::-moz-meter-bar {
|
||||
background: url(../assets/images/armor.png) repeat-x left center;
|
||||
}
|
||||
}
|
||||
|
@ -16,11 +16,15 @@
|
||||
|
||||
import {DynmapMarkerSetUpdates, DynmapTileUpdate, DynmapUpdate} from "@/dynmap";
|
||||
import {
|
||||
LiveAtlasArea, LiveAtlasChat,
|
||||
LiveAtlasArea,
|
||||
LiveAtlasChat,
|
||||
LiveAtlasCircle,
|
||||
LiveAtlasComponentConfig, LiveAtlasDimension,
|
||||
LiveAtlasComponentConfig,
|
||||
LiveAtlasDimension,
|
||||
LiveAtlasLine,
|
||||
LiveAtlasMarker, LiveAtlasServerConfig, LiveAtlasServerMessageConfig,
|
||||
LiveAtlasMarker,
|
||||
LiveAtlasServerConfig,
|
||||
LiveAtlasServerMessageConfig,
|
||||
LiveAtlasWorldDefinition
|
||||
} from "@/index";
|
||||
import {getPoints} from "@/util/areas";
|
||||
@ -150,11 +154,16 @@ export function buildComponents(response: any): LiveAtlasComponentConfig {
|
||||
hideByDefault: component.hidebydefault || false,
|
||||
layerName: component.label || "Players",
|
||||
layerPriority: component.layerprio || 0,
|
||||
showBodies: component.showplayerbody || false,
|
||||
showSkinFaces: component.showplayerfaces || false,
|
||||
showSkins: component.showplayerfaces || false,
|
||||
imageSize: 'large',
|
||||
showHealth: component.showplayerhealth || false,
|
||||
showArmor: component.showplayerhealth || false,
|
||||
smallFaces: component.smallplayerfaces || false,
|
||||
}
|
||||
|
||||
if(component.smallplayerfaces) {
|
||||
components.playerMarkers.imageSize = 'small'
|
||||
} else if(component.showplayerbody) {
|
||||
components.playerMarkers.imageSize = 'body';
|
||||
}
|
||||
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user