This commit is contained in:
2026-03-26 12:10:21 +01:00
parent 1f4970c17c
commit d4d76db890
877 changed files with 631941 additions and 26195 deletions
Binary file not shown.

Before

Width:  |  Height:  |  Size: 577 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

@@ -1,130 +0,0 @@
import { LitElement, TemplateResult } from 'lit';
import { HomeAssistant } from 'custom-card-helpers';
import { UltraVehicleCardConfig } from '../types';
declare module 'custom-card-helpers' {
interface HomeAssistant {
__uvc_template_strings?: {
[key: string]: string;
};
}
}
export declare class UltraVehicleCard extends LitElement {
hass: HomeAssistant;
private config;
private _templateService?;
private static readonly DEFAULT_ACTIVE_STATES;
private static readonly DEFAULT_INACTIVE_STATES;
private _lastRenderTime;
private _lastImageUrl;
private _mapPopupData;
private _iconActiveStates;
private _iconsAwaitingConfirmation;
private _templateSubscriptions;
private _templateResults;
private _confirmationCancelListeners;
private _iconStateDebounceTimers;
private _highlightedSections;
static getConfigElement(): HTMLElement;
static getStubConfig(): {
title: string;
title_alignment: string;
title_size: number;
formatted_entities: boolean;
show_units: boolean;
vehicle_image_type: string;
sections_order: string[];
};
static get properties(): {
hass: {};
config: {};
};
static get styles(): import("lit").CSSResult;
setConfig(config: UltraVehicleCardConfig): void;
private _migrateBarsToIndividual;
private _cleanupInfoSections;
private _saveConfigChanges;
private _checkForGradientOrAnimationChanges;
private _forceFullRender;
protected render(): TemplateResult<1>;
private _renderImage;
private _getFriendlyName;
/**
* Check if an entity is a location tracking entity with coordinate data
*/
private _isLocationTrackingEntity;
/**
* Render a map view for location tracking entities
*/
private _renderMapImage;
private _formatValue;
private _handleImageError;
private _renderBar;
private _renderPercentageText;
private _getBarAnimationClass;
private _getEntityState;
private _renderIconRows;
private _renderIconRow;
private _renderCardIcon;
private _debouncedIconStateUpdate;
private _handleIconClick;
/**
* Shows a toast notification
* @param message The message to display
* @param type The type of toast (success, error, or info)
*/
private _showToast;
/**
* Opens a location map for the entity
*/
private _openLocationMap;
private _handleDragStart;
private _handleDragEnd;
private _hexToRgb;
private _hsToRgb;
private _colorTempToRgb;
private _getZoneInfo;
private _renderVehicleInfo;
private _computeImageStyle;
private _normalizeState;
private _renderBarLabels;
/**
* Process bar template and return the rendered result
* Similar to how templates are handled for icons
*/
private _processBarTemplate;
private _showMoreInfo;
firstUpdated(): void;
connectedCallback(): void;
disconnectedCallback(): void;
private _handleForceGradientRefresh;
private _refreshInterval;
private _setupRefreshInterval;
private _entityStates;
private _entityImageUrls;
protected updated(changedProperties: Map<string, any>): void;
private _evaluateTemplate;
private _subscribeToTemplate;
private _parseTemplateResult;
private _unsubscribeAllTemplates;
private _renderMapPopup;
private _formatCoordinates;
private _getEntityForCoordinates;
private _isDarkMode;
private _closeMapPopup;
private _shouldRenderSection;
private _cancelConfirmation;
private _checkBarSideCondition;
private _processPercentageTemplate;
private _renderInfoRowsFromConfig;
private _renderSingleInfoRow;
private _renderSingleInfoEntity;
private _handleInfoEntityClick;
private _getDisplaySections;
private _cleanupSectionsOrder;
private _ensureInfoAndIconRowsInSectionsOrder;
private _handleHighlightSections;
private _isHighlighted;
private _getHighlightClass;
private _getImageHighlightStyle;
private _handleClearHighlight;
}
-9
View File
@@ -1,9 +0,0 @@
import { LitElement } from 'lit';
export declare class UltraVehicleColorPicker extends LitElement {
value?: string;
label?: string;
private _getDisplayColor;
private _colorChanged;
render(): import("lit").TemplateResult<1>;
static get styles(): import("lit").CSSResult;
}
@@ -1,39 +0,0 @@
import { LitElement, TemplateResult } from 'lit';
import { HomeAssistant } from 'custom-card-helpers';
import { ActionImageConfig } from '../types';
export declare class ActionImageRow extends LitElement {
hass: HomeAssistant;
config: ActionImageConfig;
lang: string;
initialExpanded: boolean;
private expanded;
private _cropExpanded;
private _sliderInputValue?;
private _hasInitialized;
protected updated(changedProperties: Map<string, any>): void;
protected render(): TemplateResult<1>;
private _renderPreview;
private _renderImageInput;
private _toggleExpand;
private _handleDelete;
private _handleDuplicate;
private _handleEntityFormChange;
private _handleStateChange;
private _handleImageTypeChange;
private _handleImageUrlChange;
private _handleImageEntityFormChange;
private _handleFileUpload;
private _handleConfigChange;
private _getImageTypeName;
private _truncatePath;
private _handleDragStart;
private _handleDragEnd;
private _renderCropControls;
private _createDefaultCropSettings;
private _updateImageCrop;
private _handleWidthChange;
private _handleSliderInput;
private _handleWidthInput;
private _handleWidthInputChange;
static styles: import("lit").CSSResult;
}
@@ -1,14 +0,0 @@
import { LitElement } from 'lit';
export declare class ColorPicker extends LitElement {
value?: string;
label?: string;
configValue?: string;
showResetButton: boolean;
private _getDisplayColor;
private _rgbToHex;
private _onColorChanged;
private _fireChangeEvent;
private _resetColor;
render(): import("lit").TemplateResult<1>;
static get styles(): import("lit").CSSResult;
}
@@ -1,11 +0,0 @@
import { LitElement } from 'lit';
import { HomeAssistant } from 'custom-card-helpers';
export declare class UltraEntityPicker extends LitElement {
hass: HomeAssistant;
label: string;
value?: string;
entityFilter?: (entityId: string) => boolean;
static get styles(): import("lit").CSSResult;
protected render(): import("lit").TemplateResult<1>;
private _valueChanged;
}
@@ -1,39 +0,0 @@
import { LitElement } from 'lit';
export interface GradientStop {
id: string;
position: number;
color: string;
}
export declare function generateGradientString(stops: GradientStop[]): string;
export declare function createDefaultGradientStops(): GradientStop[];
export declare function createLinearGradient(stops: GradientStop[]): string;
export declare function getColorAtPosition(stops: GradientStop[], position: number): string;
export declare function createStopAtLargestGap(stops: GradientStop[]): GradientStop;
export declare function normalizeBoundaryStops(stops: GradientStop[]): GradientStop[];
export declare class GradientEditor extends LitElement {
stops: GradientStop[];
barSize: 'thin' | 'regular' | 'thick' | 'thiccc';
barRadius: 'round' | 'square' | 'rounded-square';
barStyle: string;
private _draggedIndex;
static styles: import("lit").CSSResult;
render(): import("lit").TemplateResult<1>;
private _renderStopItem;
private _addStop;
private _resetStops;
private _deleteStop;
private _handleColorChange;
private _handlePositionChange;
private _validateAndSortStops;
private _notifyChange;
private _dispatchResetEvent;
private _handleDragStart;
private _handleDragEnd;
private _handleDragOver;
private _handleDrop;
}
declare global {
interface HTMLElementTagNameMap {
'gradient-editor': GradientEditor;
}
}
@@ -1,4 +0,0 @@
// Ultra Vehicle Card Debug Info
// Version: 2.9.1
// Build Date: 2025-06-04T20:50:34.534Z
// Build Mode: production
@@ -1 +0,0 @@
export declare const editorStyles: import("lit").CSSResult;
@@ -1,8 +0,0 @@
import { LitElement, TemplateResult, nothing } from 'lit';
import { HomeAssistant } from 'custom-card-helpers';
export declare class AboutTab extends LitElement {
hass: HomeAssistant;
private _t;
protected render(): TemplateResult | typeof nothing;
static styles: import("lit").CSSResult;
}
@@ -1,23 +0,0 @@
import { LitElement } from 'lit';
import { HomeAssistant } from 'custom-card-helpers';
import { UltraVehicleCardConfig } from '../../types';
import '../../components/action-image-row';
export declare class ActionImagesTab extends LitElement {
hass: HomeAssistant;
config: UltraVehicleCardConfig;
private _dragOverIndex;
private _newlyAddedImageIds;
protected render(): import("lit").TemplateResult<1>;
private _handleImageConfigChange;
private _addActionImage;
private _duplicateActionImage;
private _deleteActionImage;
private _updateConfig;
private _handleRowDragOver;
private _handleDragOver;
private _handleDragLeave;
private _handleDrop;
private _handlePriorityChange;
private _t;
static styles: import("lit").CSSResult;
}
@@ -1,77 +0,0 @@
import { LitElement, TemplateResult, nothing } from 'lit';
import { HomeAssistant } from 'custom-card-helpers';
import { UltraVehicleCardConfig } from '../../types';
import '../../components/entity-picker';
import '../../components/color-picker';
import '../../components/gradient-editor';
export declare class BarsTab extends LitElement {
hass: HomeAssistant;
config: UltraVehicleCardConfig;
private _expandedBar;
private _preventExpandCollapse;
private _activeBarTabs;
private _updateStopDebounceTimer;
private _removeStopDebounceTimer;
private _updateOrderDebounceTimer;
private _gradientChangedDebounceTimer;
private _isUpdatingGradient;
private readonly DEBOUNCE_DELAY;
private readonly MAX_STOPS;
private _t;
private _generateUniqueId;
private _getFriendlyName;
private _truncateText;
private _fireConfigChanged;
private _fireForceRefreshEvent;
private _fireForceGradientRefreshEvent;
private _navigateToCustomizeTab;
private _handleGlobalBarAlignmentChange;
private _toggleBarExpand;
private _syncSectionsOrderWithBars;
private _addBar;
private _duplicateBar;
private _removeBar;
private _barValueChanged;
private _handleColorChange;
private _setNestedBarValue;
private _setActiveBarTab;
private _updateBarProperty;
private _resetBarColor;
private _resetBarSize;
private _getEnsuredGradientStops;
private _addGradientStop;
private _updateGradientStop;
private _removeGradientStop;
private _handleDuplicateStop;
private _handleGradientStopColorChange;
private _handleGradientChanged;
private _handleGradientStopDelete;
private _handleGradientReset;
protected render(): TemplateResult | typeof nothing;
private _renderBar;
private _renderBarContent;
private _renderBarConfigurationTab;
private _renderAlignmentControl;
private _renderBarColorsTab;
private _handleGradientFormChange;
private _renderBarAnimationTab;
private _renderPercentageTextSize;
private _renderPercentageOptions;
private _renderColorPickersGrid;
private _renderGradientEditor;
private _getMainBarSchema;
private _getLeftSideSchema;
private _getRightSideSchema;
private _getLeftTitleSizeSchema;
private _getLeftTextSizeSchema;
private _getRightTitleSizeSchema;
private _getRightTextSizeSchema;
private _getGradientToggleSchema;
private _prepareBarData;
static styles: import("lit").CSSResult;
private _generateGradientPreview;
private _updateGradientStopsOrder;
private _updateBarCondition;
private _renderLeftSideConditionFields;
private _renderRightSideConditionFields;
}
@@ -1,49 +0,0 @@
import { LitElement, TemplateResult, nothing } from 'lit';
import { HomeAssistant } from 'custom-card-helpers';
import { UltraVehicleCardConfig } from '../../types';
export declare class CustomizeTab extends LitElement {
hass: HomeAssistant;
config: UltraVehicleCardConfig;
private _draggedSection;
private _expandedSectionId;
private _dropTargetSection;
private _layoutDescriptionsExpanded;
private _dropTargetColumn;
private _t;
private _fireConfigChanged;
private _getFriendlyName;
private _truncateText;
private _valueChanged;
private _handleSectionDragStart;
private _handleSectionDragEnd;
private _handleSectionDragOver;
private _handleSectionDragLeave;
private _handleSectionDrop;
private _handleColumnDragOver;
private _handleColumnDragLeave;
private _getDisplaySections;
private _getExpandedConfigSections;
private _handleColumnDrop;
private _rearrangeSections;
private _toggleSectionExpand;
private _updateSectionMargin;
private _updateSectionCondition;
private _updateSectionBreakConfig;
private _resetSectionBreakColor;
private _handleAddSectionBreak;
private _handleDeleteSectionBreak;
protected render(): TemplateResult | typeof nothing;
protected updated(changedProperties: Map<string, any>): void;
private _renderCustomizeTab;
private _renderDraggableSections;
private _renderGlobalCssSection;
getSectionIcon(sectionId: string): string;
getSectionLabel(sectionId: string): string;
private _cleanupSectionsOrder;
private _handleConditionTypeChange;
private _updateEntityCondition;
private _updateStateCondition;
private _getSectionTemplate;
private _updateSectionTemplate;
static styles: import("lit").CSSResult;
}
@@ -1,65 +0,0 @@
import { LitElement, TemplateResult, nothing } from 'lit';
import { HomeAssistant } from 'custom-card-helpers';
import { UltraVehicleCardConfig } from '../../types';
import '../../components/entity-picker';
import '../../components/color-picker';
import '../../components/gradient-editor';
export declare class IconsTab extends LitElement {
hass: HomeAssistant;
config: UltraVehicleCardConfig;
private _expandedIconRow;
private _expandedIcon;
private _activeIconTabs;
private _layoutHelpExpanded;
private _rowSettingsExpanded;
private _stateSettingsExpanded;
private _t;
private _generateUniqueId;
private _getFriendlyName;
private _truncateText;
private _formatFieldName;
private _fireConfigChanged;
private _addIconRow;
private _removeIconRow;
private _duplicateIconRow;
private _duplicateIcon;
private _toggleIconRowExpand;
private _updateIconRowConfig;
private _addIcon;
private _removeIcon;
private _toggleIconEdit;
private _updateIconConfig;
private _createDefaultIconRow;
private _createDefaultIcon;
private _resetIconColor;
private _resetIconNameColor;
private _resetIconStateColor;
private _resetIconAppearanceColor;
private _resetIconSize;
/**
* Helper to get the icon defined for an entity in Home Assistant,
* falling back to domain/device_class defaults.
*/
private _getEntityIcon;
protected render(): TemplateResult | typeof nothing;
private _renderIconRow;
private _renderIconRowContent;
private _renderIcon;
private _renderIconContent;
private _renderIconGeneralTab;
private _getIconGeneralSchema;
private _getClickActionDescription;
private _renderIconAppearanceTab;
private _getIconAppearanceGeneralSchema;
private _getIconAppearanceIconSchema;
private _getIconAppearanceContainerSchema;
private _getIconAppearanceTextSizeSchema;
private _getIconAppearanceTextAlignmentSchema;
private _renderIconStatesTab;
private _renderColorPicker;
private _toggleLayoutHelp;
private _toggleRowSettings;
private _toggleStateSettings;
static styles: import("lit").CSSResult;
private _navigateToCustomizeTab;
}
@@ -1,61 +0,0 @@
import { LitElement, TemplateResult, nothing } from 'lit';
import { HomeAssistant } from 'custom-card-helpers';
import { UltraVehicleCardConfig } from '../../types';
import '../../components/entity-picker';
import '../../components/color-picker';
export declare class InfoTab extends LitElement {
hass: HomeAssistant;
config: UltraVehicleCardConfig;
private _templateService?;
private _expandedInfoRow;
private _expandedInfoEntity;
private _activeInfoTabs;
private _rowSettingsExpanded;
private _draggedEntity;
private _dropTargetEntity;
private _isTemplateEditing;
private _t;
private _generateUniqueId;
private _getFriendlyName;
private _truncateText;
private _formatFieldName;
private _fireConfigChanged;
private _addInfoRow;
private _removeInfoRow;
private _duplicateInfoRow;
private _toggleInfoRowExpand;
private _updateInfoRowConfig;
private _addInfoEntity;
private _removeInfoEntity;
private _duplicateInfoEntity;
private _toggleInfoEntityEdit;
private _updateInfoEntityConfig;
/**
* Helper to get the icon defined for an entity in Home Assistant,
* falling back to domain/device_class defaults.
*/
private _getEntityIcon;
private _createDefaultInfoRow;
private _createDefaultInfoEntity;
private _toggleRowSettings;
private _navigateToCustomizeTab;
private _setTemplateEditingMode;
protected render(): TemplateResult | typeof nothing;
private _renderMigrationNotice;
private _migrateFromLegacy;
private _renderInfoRow;
private _renderInfoRowContent;
private _renderInfoEntity;
private _renderInfoEntityContent;
private _handleInfoEntityDragStart;
private _handleInfoEntityDragEnd;
private _handleInfoEntityDragOver;
private _handleInfoEntityDragLeave;
private _handleInfoEntityDrop;
private _rearrangeInfoEntities;
static styles: import("lit").CSSResult;
connectedCallback(): void;
disconnectedCallback(): void;
protected updated(changedProperties: Map<string, any>): void;
private _handleGlobalClick;
}
@@ -1,41 +0,0 @@
import { LitElement, TemplateResult } from 'lit';
import { HomeAssistant } from 'custom-card-helpers';
import { UltraVehicleCardConfig } from '../../types';
import '../../components/entity-picker';
import '../../components/color-picker';
import '../..//components/gradient-editor';
import './action-images-tab';
export declare class SettingsTab extends LitElement {
hass: HomeAssistant;
private _internalConfig;
set config(value: UltraVehicleCardConfig);
get config(): UltraVehicleCardConfig;
private get _config();
private _vehicleCropExpanded;
private _activeSubTab;
private _displayedWidth;
private _rowSettingsExpanded;
private _activeEntityTabs;
private _t;
private _generateUniqueId;
private _formatFieldName;
private _truncatePath;
private _valueChanged;
private _getImageSchema;
private _dispatchFileUpload;
private _resetTitleSize;
private _createDefaultCropSettings;
private _renderCropSliders;
private _updateImageCrop;
private _renderGeneralTab;
protected render(): TemplateResult;
private _handleConfigChangedFromActionImages;
private _handleFileUploadEvent;
private _handleInputWidth;
private _handleInputWidthChange;
private _handleSliderInput;
private _handleImageWidthChange;
private _needsMigration;
private _performMigration;
static styles: import("lit").CSSResult;
}
@@ -1,171 +0,0 @@
import { LitElement, nothing } from 'lit';
import { HomeAssistant } from 'custom-card-helpers';
import { UltraVehicleCardConfig } from '../types';
import '../components/entity-picker';
import '../components/color-picker';
import '../components/gradient-editor';
export declare class UltraVehicleCardEditor extends LitElement {
hass: HomeAssistant;
private config;
private activeTab;
private _showEntityList;
private _activeField;
private _entityFilter;
private _entities;
private _expandedBar;
private _preventExpandCollapse;
private _draggedBarIndex;
private _dropTargetIndex;
private _expandedIconRow;
private _expandedIcon;
private _draggedIconRow;
private _draggedIcon;
private _dropTargetRow;
private _dropTargetIcon;
private _cropperActive;
private _cropperImage;
private _cropperTargetField;
private _vehicleCropExpanded;
private _actionCropExpanded;
private _draggedBar;
private _dropTargetBar;
private _dropTargetIconRow;
private _draggedSection;
private _expandedSectionId;
private _editorVersion;
private _activeIconTabs;
private _activeBarTabs;
private _gradientEditorKeys;
private _latestStopPositions;
setConfig(config: UltraVehicleCardConfig): void;
private _migrateToIndividualSections;
private handleFileUpload;
private _getCleanConfig;
private _updateConfig;
private _configChangedTimeout;
private _valueChanged;
private _barValueChanged;
private _setNestedValue;
private _toggleBarExpand;
private _addBar;
private _duplicateBar;
private _removeBar;
private _renderSettingsTab;
private _renderCustomizeTab;
private _renderBarsTab;
private _truncateText;
private _getFriendlyName;
private _renderBar;
private _renderBarConfigurationTab;
private _renderBarColorsTab;
private _renderBarAnimationTab;
private _setActiveBarTab;
private _getMainBarSchema;
private _getLeftSideSchema;
private _getRightSideSchema;
private _prepareBarData;
private _renderColorPickersGrid;
private _convertCssVariableToColor;
private _resetBarColor;
private _updateBarProperty;
private _fireForceGradientRefreshEvent;
private _renderActionSchema;
private _getEntityStateOptions;
private _handleActionImageUpload;
private _renderIconsTab;
private _renderIconRow;
private _renderIcon;
private _addIconRow;
private _removeIconRow;
private _duplicateIconRow;
private _duplicateIcon;
private _toggleIconRowExpand;
private _updateIconRowConfig;
private _addIcon;
private _removeIcon;
private _toggleIconEdit;
private _updateIconConfig;
private _getAlignmentLabel;
private _getSpacingValue;
private _handleIconRowDragStart;
private _handleIconRowDragEnd;
private _handleIconRowDragOver;
private _handleIconRowDragLeave;
private _handleIconRowDrop;
private _handleIconDragStart;
private _handleIconDragEnd;
private _handleIconDragOver;
private _handleIconDragLeave;
private _handleIconDrop;
private _rearrangeIcons;
render(): import("lit").TemplateResult<1> | typeof nothing;
static get styles(): import("lit").CSSResult;
firstUpdated(): void;
private _refreshEntityList;
private _onEntityInputChange;
private _onEntityFocus;
private _getFilteredEntities;
private _selectEntity;
private _handleDragStart;
private _handleDragEnd;
private _handleDragOver;
private _handleDragLeave;
private _handleDrop;
private _rearrangeBars;
private _createDefaultConfig;
private _handleFileInputChange;
private _formatFieldName;
private _createDefaultIconRow;
private _createDefaultIcon;
private _generateUniqueId;
private _rearrangeIconRows;
private _createDefaultCropSettings;
private _loadCropperJS;
private _renderImageCropper;
private _applyCrop;
updated(changedProperties: any): void;
private _renderCropSliders;
private _renderIconRows;
private _renderCardIconRow;
private _renderCardIcon;
private _truncatePath;
private _resetIconNameColor;
private _getImageSchema;
private _handleImageUpload;
private _resetIconColor;
private _resetIconAppearanceColor;
private _resetIconSize;
private _handleIconClick;
private _updateImageCrop;
private _resetTitleSize;
private _resetBarSize;
private _ensureGradientStops;
private _renderDraggableSections;
private _dropTargetSection;
private _dropTargetColumn;
private _handleSectionDragStart;
private _handleSectionDragEnd;
private _handleSectionDragOver;
private _handleSectionDragLeave;
private _handleSectionDrop;
private _handleColumnDragOver;
private _handleColumnDragLeave;
private _handleColumnDrop;
private _rearrangeSections;
private _toggleSectionExpand;
private _updateSectionMargin;
private _getLeftTitleSizeSchema;
private _getLeftTextSizeSchema;
private _getRightTitleSizeSchema;
private _getRightTextSizeSchema;
private _getGradientToggleSchema;
private _renderGradientEditor;
private _addGradientStop;
private _updateGradientStop;
private _removeGradientStop;
private _updateGradientStopsOrder;
private _generateGradientPreview;
private _renderGlobalCssSection;
private _renderAboutTab;
private _t;
}
@@ -1,63 +0,0 @@
import { LitElement, nothing } from 'lit';
import { HomeAssistant } from 'custom-card-helpers';
import { UltraVehicleCardConfig } from '../types';
import '../components/entity-picker';
import '../components/color-picker';
import '../components/gradient-editor';
import './tabs/settings-tab';
import './tabs/bars-tab';
import './tabs/icons-tab';
import './tabs/customize-tab';
import './tabs/about-tab';
import './tabs/info-tab';
export declare class UltraVehicleCardEditor extends LitElement {
hass: HomeAssistant;
private config;
private activeTab;
private _highlightedSections;
private _highlightTimeout;
private _cropperActive;
private _cropperImage;
private _cropperTargetField;
private _vehicleCropExpanded;
private _actionCropExpanded;
private _showEntityList;
private _activeField;
private _entityFilter;
private _entities;
private _editorVersion;
private _configChangedTimeout;
setConfig(config: UltraVehicleCardConfig): void;
private _migrateToIndividualSections;
private _handleFileUploadEvent;
private _getCleanConfig;
private _updateConfig;
private _updateConfigFromEvent;
private _fireConfigChanged;
private _getFriendlyName;
private _truncateText;
private _generateUniqueId;
private _formatFieldName;
private _getImageSchema;
private _renderCropSliders;
private _updateImageCrop;
private _resetTitleSize;
private _t;
private _fireForceGradientRefreshEvent;
private _forceSaveConfig;
private _handleRequestTabChange;
private _getHighlightedSectionsForTab;
private _updateHighlightedSections;
render(): import("lit").TemplateResult<1> | typeof nothing;
static get styles(): import("lit").CSSResult;
firstUpdated(): void;
private _refreshEntityList;
private _onEntityInputChange;
private _onEntityFocus;
private _getFilteredEntities;
private _selectEntity;
private _loadCropperJS;
private _renderImageCropper;
private _applyCrop;
updated(changedProperties: any): void;
}
-11
View File
@@ -1,11 +0,0 @@
import { LitElement } from 'lit';
import { HomeAssistant } from 'custom-card-helpers';
export declare class UltraEntityPicker extends LitElement {
hass: HomeAssistant;
label: string;
value?: string;
entityFilter?: (entityId: string) => boolean;
static get styles(): import("lit").CSSResult;
protected render(): import("lit").TemplateResult<1>;
private _valueChanged;
}
-4
View File
@@ -1,4 +0,0 @@
import './cards/ultra-vehicle-card';
import './editor/ultra-vehicle-card-editor';
import './components/entity-picker';
export { TemplateService } from './services/template-service';
-26
View File
@@ -1,26 +0,0 @@
export declare function localize(key: string, lang: string, fallback?: string): string;
/**
* Utility function to check if a translation key exists in the English translations
* This is used during development to ensure all used keys have been added to the translation files
*
* @param key The translation key to check
* @returns True if the key exists, false otherwise
*/
export declare function hasTranslation(key: string): boolean;
/**
* Development helper function to log missing translations
* Use during development to identify keys that need to be added to translations
*
* @param key The translation key being accessed
* @param fallback The fallback text provided
*/
export declare function logMissingTranslation(key: string, fallback?: string): void;
/**
* Enhanced localize function that also logs missing translations during development
*
* @param key The translation key
* @param lang The current language
* @param fallback Optional fallback text
* @returns The translated string
*/
export declare function localizeWithLogging(key: string, lang: string, fallback?: string): string;
@@ -1,62 +0,0 @@
import { HomeAssistant } from 'custom-card-helpers';
/**
* Extended HomeAssistant interface to store template string results
* This is declared in the main file as well for backwards compatibility
*/
declare module 'custom-card-helpers' {
interface HomeAssistant {
__uvc_template_strings?: {
[key: string]: string;
};
}
}
/**
* Service class for handling template evaluation and subscription in Ultra Vehicle Card
*/
export declare class TemplateService {
private hass;
private _templateSubscriptions;
private _templateResults;
private _evaluationCache;
private readonly CACHE_TTL;
constructor(hass: HomeAssistant);
/**
* Get a specific template result
*/
getTemplateResult(templateKey: string): boolean | undefined;
/**
* Check if a template subscription exists
*/
hasTemplateSubscription(templateKey: string): boolean;
/**
* Get all template results as a map
*/
getAllTemplateResults(): Map<string, boolean>;
/**
* Evaluates a template string and returns a boolean result
* @param template The template string to evaluate
* @returns Promise resolving to a boolean representing the template evaluation
*/
evaluateTemplate(template: string): Promise<boolean>;
/**
* Subscribe to a template and store results for later use
* @param template The template string to subscribe to
* @param templateKey The unique key to identify this template subscription
*/
subscribeToTemplate(template: string, templateKey: string, onResultChanged?: () => void): Promise<void>;
/**
* Helper method to parse template results consistently
* @param result The raw result from the template evaluation
* @param templateKey Optional template key for context
* @returns Boolean interpretation of the template result
*/
parseTemplateResult(result: any, templateKey?: string): boolean;
/**
* Unsubscribe from all template subscriptions
*/
unsubscribeAllTemplates(): Promise<void>;
/**
* Update the Home Assistant reference
*/
updateHass(hass: HomeAssistant): void;
}
-289
View File
@@ -1,289 +0,0 @@
import { GradientStop } from './components/gradient-editor';
export { GradientStop };
export interface SectionCondition {
type: 'none' | 'show' | 'hide';
entity: string;
state: string;
}
export interface SectionConditions {
[sectionId: string]: SectionCondition;
}
export interface SectionTemplate {
template_mode?: boolean;
template?: string;
}
export interface SectionTemplates {
[sectionId: string]: SectionTemplate;
}
export type UltraVehicleCardConfig = {
type?: string;
title?: string;
title_alignment?: 'left' | 'center' | 'right';
title_size?: string | number;
title_color?: string;
card_background?: string;
vehicle_image_type?: 'default' | 'upload' | 'url' | 'entity' | 'none';
vehicle_image?: string;
vehicle_image_entity?: string;
vehicle_image_width?: number;
default_vehicle_image?: string;
status_image_type?: 'none' | 'upload' | 'entity';
status_image?: string;
status_image_entity?: string;
status_image_trigger_entity?: string;
layout_type?: 'single' | 'double' | 'dashboard' | 'half_full' | 'full_half';
column_width?: '50-50' | '30-70' | '70-30' | '40-60' | '60-40';
formatted_entities?: boolean;
show_units?: boolean;
show_action_toasts?: boolean;
help_highlight?: boolean;
top_view_side_margin?: number;
top_view_middle_spacing?: number;
top_view_vertical_spacing?: number;
icon_text_position?: 'bottom' | 'top' | 'left' | 'right';
icon_vertical_alignment?: 'top' | 'center' | 'bottom';
icon_text_size?: 'small' | 'medium' | 'large';
battery_level_entity?: string;
show_battery?: boolean;
battery_range_entity?: string;
show_battery_range?: boolean;
charging_status_entity?: string;
show_charging_status?: boolean;
charge_limit_entity?: string;
show_charge_limit?: boolean;
location_entity?: string;
show_location?: boolean;
location_icon_color?: string;
location_text_color?: string;
location_text_size?: string | number;
mileage_entity?: string;
show_mileage?: boolean;
mileage_icon_color?: string;
mileage_text_color?: string;
mileage_text_size?: string | number;
car_state_entity?: string;
show_car_state?: boolean;
car_state_text_color?: string;
car_state_text_size?: string | number;
car_state_template_mode?: boolean;
car_state_template?: string;
show_info_icons?: boolean;
bars?: BarConfig[];
action_entity?: string;
action_state?: string;
action_image_type?: 'default' | 'upload' | 'url' | 'entity' | 'none';
action_image?: string;
action_image_entity?: string;
action_image_width?: number;
action_images?: ActionImageConfig[];
action_image_priority?: 'priority' | 'newest';
icon_rows?: IconRowConfig[];
info_rows?: InfoRowConfig[];
vehicle_image_crop?: ImageCropSettings;
action_image_crop?: ImageCropSettings;
sections_order?: string[];
sections_columns?: SectionColumns;
bar_row_alignment?: 'flex-start' | 'center' | 'flex-end';
hidden_sections?: string[];
section_styles?: SectionStyles;
section_conditions?: SectionConditions;
section_templates?: SectionTemplates;
global_css?: string;
section_breaks?: SectionBreakConfig[];
};
export type SectionColumns = {
[sectionId: string]: 'right' | 'top' | 'top_middle' | 'left_middle' | 'right_middle' | 'bottom_middle' | 'bottom' | 'middle' | 'half_full_row1_left' | 'half_full_row1_right' | 'half_full_row2_full' | 'full_half_row1_full' | 'full_half_row2_left' | 'full_half_row2_right';
};
export interface BarConfig {
entity: string;
limit_entity?: string;
limit_indicator_color?: string;
left_entity?: string;
right_entity?: string;
left_title?: string;
right_title?: string;
bar_color?: string;
background_color?: string;
border_color?: string;
left_title_color?: string;
left_text_color?: string;
right_title_color?: string;
right_text_color?: string;
percentage_text_color?: string;
left_title_size?: string | number;
left_text_size?: string | number;
right_title_size?: string | number;
right_text_size?: string | number;
percentage_text_size?: string | number;
bar_size?: 'thin' | 'regular' | 'thick' | 'thiccc';
bar_radius?: 'round' | 'square' | 'rounded-square';
bar_style?: 'flat' | 'glossy' | 'embossed' | 'inset' | 'gradient' | 'neon' | 'outline' | 'glass' | 'metallic' | 'neumorphic' | 'dashed';
show_left?: boolean;
show_right?: boolean;
show_percentage?: boolean;
alignment?: string;
width?: string;
use_gradient?: boolean;
gradient_stops?: GradientStop[];
gradient_display_mode?: 'full' | 'value_based' | 'cropped';
animation_entity?: string;
animation_state?: string;
animation_type?: string;
action_animation_entity?: string;
action_animation_state?: string;
action_animation?: string;
left_condition?: SectionCondition;
right_condition?: SectionCondition;
left_template_mode?: boolean;
left_template?: string;
right_template_mode?: boolean;
right_template?: string;
percentage_type?: 'entity' | 'difference';
percentage_amount_entity?: string;
percentage_total_entity?: string;
}
export interface CustomCard {
type: string;
name: string;
description: string;
draggable?: boolean;
}
export interface IconConfig {
entity: string;
name?: string;
icon_inactive?: string;
icon_active?: string;
color_inactive?: string;
color_active?: string;
inactive_state?: string;
active_state?: string;
inactive_template_mode?: boolean;
active_template_mode?: boolean;
inactive_template?: string;
active_template?: string;
active_state_text?: string;
inactive_state_text?: string;
active_animation?: 'none' | 'pulse' | 'vibrate' | 'rotate-left' | 'rotate-right' | 'hover' | 'fade' | 'scale' | 'bounce' | 'shake' | 'tada';
inactive_animation?: 'none' | 'pulse' | 'vibrate' | 'rotate-left' | 'rotate-right' | 'hover' | 'fade' | 'scale' | 'bounce' | 'shake' | 'tada';
show_state?: boolean;
show_name?: boolean;
show_name_active?: boolean;
show_name_inactive?: boolean;
show_state_active?: boolean;
show_state_inactive?: boolean;
show_units?: boolean;
show_icon_active?: boolean;
show_icon_inactive?: boolean;
use_entity_color_for_icon?: boolean;
use_entity_color_for_icon_active?: boolean;
use_entity_color_for_icon_inactive?: boolean;
use_entity_color_for_icon_background?: boolean;
use_entity_color_for_container_background?: boolean;
on_click_action?: 'toggle' | 'more-info' | 'navigate' | 'url' | 'call-service' | 'perform-action' | 'show-location-map' | 'location-map' | 'voice-assistant' | 'trigger' | 'no-action';
navigation_path?: string;
url?: string;
service?: string;
service_data?: Record<string, any> | string;
action?: Record<string, any> | string;
text_position?: 'top' | 'bottom' | 'left' | 'right';
vertical_alignment?: 'flex-start' | 'center' | 'flex-end';
text_alignment?: 'left' | 'center' | 'right';
icon_size?: string | number;
text_size?: string | number;
name_color_active?: string;
name_color_inactive?: string;
state_color_active?: string;
state_color_inactive?: string;
icon_background?: 'none' | 'circle' | 'square' | 'rounded-square';
icon_background_color?: string;
container_background?: 'none' | 'circle' | 'square' | 'rounded-square';
container_background_color?: string;
container_width?: number;
draggable?: boolean;
active_icon_template?: string;
inactive_icon_template?: string;
active_state_template?: string;
inactive_state_template?: string;
}
export interface IconRowConfig {
id: string;
width?: string;
alignment?: string;
vertical_alignment?: string;
spacing?: string;
columns?: number;
icons: IconConfig[];
}
export interface ImageCropSettings {
top: number;
right: number;
bottom: number;
left: number;
width?: number;
height?: number;
x?: number;
y?: number;
}
export interface SectionStyleSettings {
marginTop?: number;
marginBottom?: number;
}
export interface SectionStyles {
[sectionId: string]: SectionStyleSettings;
}
export interface ActionImageConfig {
id: string;
entity: string;
state: string;
image_type: 'upload' | 'url' | 'entity' | 'none';
image?: string;
image_entity?: string;
image_width?: number;
image_crop?: ImageCropSettings;
priority?: number;
template_mode?: boolean;
template?: string;
}
export interface SectionBreakConfig {
id: string;
break_style?: 'blank' | 'line' | 'double_line' | 'dotted' | 'double_dotted' | 'shadow';
break_thickness?: number;
break_width_percent?: number;
break_color?: string;
}
export interface InfoEntityConfig {
id: string;
entity: string;
name?: string;
icon?: string;
show_icon?: boolean;
show_name?: boolean;
text_size?: string | number;
name_size?: string | number;
icon_size?: string | number;
icon_color?: string;
name_color?: string;
text_color?: string | 'primary' | 'secondary' | 'accent' | 'custom' | '';
custom_text_color?: string;
value_template?: string;
template_mode?: boolean;
on_click_action?: 'more-info' | 'navigate' | 'url' | 'call-service' | 'none';
navigation_path?: string;
url?: string;
service?: string;
service_data?: Record<string, any> | string;
}
export interface InfoRowConfig {
id: string;
width: string;
alignment: string;
vertical_alignment?: string;
spacing: string;
columns?: number;
allow_wrap?: boolean;
info_entities: InfoEntityConfig[];
row_header?: string;
row_header_size?: number;
row_header_color?: string;
show_row_header?: boolean;
}
-165
View File
@@ -1,165 +0,0 @@
import { GradientStop } from '../components/gradient-editor';
export interface UltraVehicleCardConfig {
type?: string;
title?: string;
title_alignment?: 'left' | 'center' | 'right';
vehicle_image_type?: 'default' | 'upload' | 'url' | 'entity' | 'none';
vehicle_image?: string;
vehicle_image_entity?: string;
vehicle_image_width?: number;
default_vehicle_image?: string;
status_image_type?: 'none' | 'upload' | 'entity';
status_image?: string;
status_image_entity?: string;
status_image_trigger_entity?: string;
layout_type?: 'single' | 'double';
formatted_entities?: boolean;
show_units?: boolean;
battery_level_entity?: string;
show_battery?: boolean;
battery_range_entity?: string;
show_battery_range?: boolean;
charging_status_entity?: string;
show_charging_status?: boolean;
charge_limit_entity?: string;
show_charge_limit?: boolean;
location_entity?: string;
show_location?: boolean;
mileage_entity?: string;
show_mileage?: boolean;
car_state_entity?: string;
show_car_state?: boolean;
bars?: BarConfig[];
action_entity?: string;
action_state?: string;
action_image_type?: 'default' | 'upload' | 'url' | 'entity' | 'none';
action_image?: string;
action_image_entity?: string;
action_image_width?: number;
action_images?: {
[entityId: string]: {
[state: string]: string;
};
};
icon_rows?: IconRowConfig[];
vehicle_image_crop?: ImageCropSettings;
action_image_crop?: ImageCropSettings;
sections_order?: string[];
sections_columns?: {
[key: string]: 'left' | 'right';
};
}
export interface BarConfig {
entity: string;
left_title?: string;
left_entity?: string;
right_title?: string;
right_entity?: string;
bar_color?: string;
background_color?: string;
border_color?: string;
left_title_color?: string;
left_text_color?: string;
right_title_color?: string;
right_text_color?: string;
percentage_text_color?: string;
limit_entity?: string;
limit_indicator_color?: string;
left_title_size?: string | number;
left_text_size?: string | number;
right_title_size?: string | number;
right_text_size?: string | number;
percentage_text_size?: string | number;
bar_size?: 'thin' | 'regular' | 'thick' | 'thiccc';
bar_radius?: 'round' | 'square' | 'rounded-square';
show_left?: boolean;
show_right?: boolean;
show_percentage?: boolean;
alignment?: 'flex-start' | 'center' | 'flex-end' | 'space-between';
width?: '25' | '50' | '75' | '100';
use_gradient?: boolean;
gradient_stops?: GradientStop[];
gradient_display_mode?: 'full' | 'value_based';
animation_entity?: string;
animation_state?: string;
animation_type?: 'charging_lines' | 'fill_repeat' | 'pulse' | 'glow' | 'rainbow';
percentage_type?: 'entity' | 'difference' | 'attribute' | 'template';
percentage_amount_entity?: string;
percentage_total_entity?: string;
percentage_attribute?: string;
percentage_template?: string;
action_animation_entity?: string;
action_animation_state?: string;
action_animation?: string;
}
export interface CustomCard {
type: string;
name: string;
description: string;
preview?: boolean;
documentationURL?: string;
version?: string;
}
export interface IconConfig {
entity: string;
icon_inactive: string;
icon_active?: string;
color_inactive: string;
color_active?: string;
inactive_state?: string;
active_state?: string;
show_state?: boolean;
show_name?: boolean;
show_units?: boolean;
name?: string;
on_click_action?: string;
active_template_mode?: boolean;
active_template?: string;
inactive_template_mode?: boolean;
inactive_template?: string;
active_state_text?: string;
inactive_state_text?: string;
icon_size?: number | string;
text_size?: number | string;
text_position?: 'bottom' | 'top' | 'left' | 'right';
vertical_alignment?: 'flex-start' | 'center' | 'flex-end';
text_alignment?: 'left' | 'center' | 'right';
icon_background?: 'none' | 'circle' | 'square' | 'rounded-square';
icon_background_color?: string;
container_background?: 'none' | 'circle' | 'square' | 'rounded-square';
container_background_color?: string;
container_width?: number;
use_entity_color_for_icon?: boolean;
use_entity_color_for_icon_active?: boolean;
use_entity_color_for_icon_inactive?: boolean;
use_entity_color_for_icon_background?: boolean;
use_entity_color_for_container_background?: boolean;
show_icon_active?: boolean;
show_icon_inactive?: boolean;
show_name_active?: boolean;
show_name_inactive?: boolean;
show_state_active?: boolean;
show_state_inactive?: boolean;
name_color_active?: string;
name_color_inactive?: string;
state_color_active?: string;
state_color_inactive?: string;
service?: string;
service_data?: string | Record<string, any>;
navigation_path?: string;
}
export interface IconRowConfig {
id: string;
width?: string;
alignment?: string;
vertical_alignment?: string;
spacing?: string;
columns?: number;
icons: IconConfig[];
}
export interface ImageCropSettings {
top: number;
right: number;
bottom: number;
left: number;
}
File diff suppressed because one or more lines are too long
@@ -1,17 +0,0 @@
/**
* @license
* Copyright 2017 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/
/**
* @license
* Copyright 2019 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/
/**
* @license
* Copyright 2020 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/
-8
View File
@@ -1,8 +0,0 @@
export declare const DEFAULT_VEHICLE_IMAGE = "/hacsfiles/Ultra-Vehicle-Card/assets/default-car.png";
export declare const DEFAULT_CONFIG: {
title: string;
title_alignment: string;
formatted_entities: boolean;
};
export declare const truncateText: (text: string, maxLength?: number) => string;
export declare const hexToRgb: (colorValue: string) => string;
@@ -1,23 +0,0 @@
import { HomeAssistant } from 'custom-card-helpers';
export interface ImageUploadResponse {
path: string;
file_id: string;
success: boolean;
error?: string;
warning?: string;
}
/**
* Uploads a file to the Home Assistant media source OR older image API.
* @param hass The Home Assistant object.
* @param file The file to upload.
* @returns The path of the uploaded file (/api/image/serve/<id> format).
* @throws An error if the upload fails or the response is invalid.
*/
export declare function uploadImage(hass: HomeAssistant, file: File): Promise<string>;
/**
* Gets the full URL for an uploaded image
* @param hass - Home Assistant instance
* @param path - Image path returned from upload
* @returns Full URL to the image
*/
export declare function getImageUrl(hass: HomeAssistant, path: string): string;
@@ -1,7 +0,0 @@
import { UltraVehicleCardConfig } from '../types';
/**
* Migrates a configuration object from version 1.x to the current format.
* @param oldConfig The configuration object from version 1.x.
* @returns The migrated configuration object conforming to UltraVehicleCardConfig.
*/
export declare function migrateV1Config(oldConfig: any): UltraVehicleCardConfig;
@@ -1,27 +0,0 @@
/**
* Translation Helper Utilities
*
* This file provides utilities to help developers manage translations
* in the Ultra Vehicle Card project. These functions are intended
* for development use only and will not be included in production builds.
*/
/**
* Adds a new translation entry to the collection.
* This is used during development to mark strings that need to be added
* to the translation files.
*
* @param fullKey The full dot-notation key for the translation (e.g., 'editor.vehicle_info.title')
* @param text The English text for this translation
* @param description Optional description to explain the context of this string
*/
export declare function addTranslation(fullKey: string, text: string, description?: string): void;
/**
* Logs all collected translation entries that need to be added to the translation files.
* Call this function in development to see all the translations that need to be added.
*/
export declare function logNewTranslations(): void;
/**
* Clears all collected translation entries.
* Call this after you've added the translations to the files.
*/
export declare function clearNewTranslations(): void;
-5
View File
@@ -1,5 +0,0 @@
/**
* Ultra Vehicle Card Version
* This is the single source of truth for version information
*/
export declare const VERSION = "2.9.1";
@@ -1,18 +0,0 @@
/**
* Ultra Vehicle Card Version
* v2.9.1
*
* This file is auto-generated from src/version.ts
* DO NOT MODIFY DIRECTLY
*/
let version = "undefined";
function setVersion(value) {
version = value;
}
// Set default version (will be overridden by card)
setVersion('2.9.1');
export { version, setVersion };
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
import{DateTime}from"./luxon.min.js";class BetterMomentCard extends HTMLElement{set hass(hass){this.hass_obj=hass;this.createTime()}createTime(){if(!this.content){this.innerHTML=`<ha-card><div class="card-content" ${this.config.parentStyle?'style="'+this.config.parentStyle+';"':""}></div>${this.config.parentHTML?""+this.config.parentHTML+"":""}</ha-card>`;this.content=this.querySelector("div");var config=this.config,elm=[];if(this.config.moment?.[0]){Object.keys(config.moment).forEach((k=>{elm[k]=document.createElement("div");elm[k].setAttribute("id","moment-"+k);config.moment[k].parentStyle?elm[k].style.cssText=config.moment[k].parentStyle:null;this.content.appendChild(elm[k])}));let dtMatrix=(f="HH:mm:ss",tz,loc,locs)=>{let dt=DateTime.now();locs=typeof locs==="string"?JSON.parse(locs)||false:locs;if(tz){if(tz.startsWith("useEntity")){let match=tz.match(/useEntity\[(.*?)\]/)?.[1].split(".");let entity=this.hass_obj.states[`${match[0]}.${match[1]}`];tz=entity?match.slice(2).reduce(((acc,key)=>acc?.[key]),entity):tz}dt=dt.setZone(tz==="useHass"?this.hass_obj.config.time_zone:tz)}if(loc)dt=dt.setLocale(loc);return locs?dt.toLocaleString(locs):dt.toFormat(f)};let updateDom=()=>{Object.keys(config.moment).forEach((k=>{let html,template=(config.moment[k].templateRaw||config.moment[k].template)?.toString();if(template&&typeof template==="string"&&(config.moment[k].helper||config.helper)){template=template.replace(/\[\[(\w+)(?:\((.*?)\))?\]\]/g,((m,h,p)=>{try{return config.moment[k].helper?.[h]||config.helper?.[h]?new Function("DateTime","hass","global_config","config","param",config.moment[k].helper?.[h]||config.helper?.[h])(DateTime,this.hass_obj,config,config.moment[k],p):"N/A"}catch(error){console.error(`Error executing helper function ${h}:`,error);return"N/A"}}))}if(config.moment[k].templateRaw){html=template.replace(/{{moment\s+format=(.*?)\s*(?:timezone=(.*?))?\s*(?:locale=(.*?))?\s*(?:localeSetting=(.*?))?}}/g,((m,f,tz,loc,locs)=>dtMatrix(f,tz||false,loc||false,locs)))}else{let dt=dtMatrix(config.moment[k].format,config.moment[k].timezone||false,config.moment[k].locale||false,config.moment[k].localeString||false);html=config.moment[k].template?template.replace(/{{moment}}/g,dt):dt}elm[k].innerHTML=html}))};updateDom();setInterval(updateDom,config.interval?config.interval:1e3)}}}setConfig(config){this.config=config;if(this.content){delete this.content;this.createTime()}}getCardSize(){return 2}static getStubConfig(){return{type:"custom:better-moment-card",parentStyle:"line-height:normal;\n",moment:[{parentStyle:"font-size:4em; text-align:center; font-weight:400;\n",templateRaw:"{{moment format=HH:mm:ss}}\n"},{parentStyle:"font-size:1.9em; text-align:center; margin-top:5px;\n",templateRaw:"{{moment format=cccc, dd LLLL}}\n"}]}}}customElements.define("better-moment-card",BetterMomentCard);window.customCards=window.customCards||[];window.customCards.push({type:"better-moment-card",name:"Better Moment Card",preview:true,documentationURL:"https://github.com/ibz0q/better-moment-card"});
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,45 +0,0 @@
const webpack = require('webpack');
const path = require('path');
const compressionPlugin = require('compression-webpack-plugin');
module.exports = {
mode: 'production',
entry: path.resolve(__dirname, 'src', 'flower-card.ts'),
output: {
filename: 'flower-card.js',
path: path.resolve(__dirname),
},
optimization: {
minimize: true
},
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
},
},
},
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/,
}
],
},
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production'),
}),
new compressionPlugin({
test: /\.js(\?.*)?$/i,
}),
],
resolve: {
extensions: ['.js', '.jsx', '.ts', '.tsx']
}
};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,22 +0,0 @@
import nodeResolve from "@rollup/plugin-node-resolve";
import json from "@rollup/plugin-json";
import typescript from "rollup-plugin-typescript2";
import { terser } from "rollup-plugin-terser";
import { getBabelOutputPlugin } from "@rollup/plugin-babel";
const dev = process.env.ROLLUP_WATCH;
export default {
input: "src/main.ts",
output: {
file: "slider-entity-row.js",
format: "es",
},
plugins: [
nodeResolve(),
json(),
typescript(),
getBabelOutputPlugin({ presets: ["@babel/preset-env"] }),
!dev && terser({ format: { comments: false } }),
],
};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,175 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- (c) ammap.com | SVG weather icons -->
<svg
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="64"
height="64"
viewbox="0 0 64 64">
<defs>
<filter id="blur" width="200%" height="200%">
<feGaussianBlur in="SourceAlpha" stdDeviation="3"/>
<feOffset dx="0" dy="4" result="offsetblur"/>
<feComponentTransfer>
<feFuncA type="linear" slope="0.05"/>
</feComponentTransfer>
<feMerge>
<feMergeNode/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
<style type="text/css"><![CDATA[
/*
** CLOUDS
*/
@keyframes am-weather-cloud-2 {
0% {
-webkit-transform: translate(0px,0px);
-moz-transform: translate(0px,0px);
-ms-transform: translate(0px,0px);
transform: translate(0px,0px);
}
50% {
-webkit-transform: translate(2px,0px);
-moz-transform: translate(2px,0px);
-ms-transform: translate(2px,0px);
transform: translate(2px,0px);
}
100% {
-webkit-transform: translate(0px,0px);
-moz-transform: translate(0px,0px);
-ms-transform: translate(0px,0px);
transform: translate(0px,0px);
}
}
.am-weather-cloud-2 {
-webkit-animation-name: am-weather-cloud-2;
-moz-animation-name: am-weather-cloud-2;
animation-name: am-weather-cloud-2;
-webkit-animation-duration: 3s;
-moz-animation-duration: 3s;
animation-duration: 3s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
/*
** SUN
*/
@keyframes am-weather-sun {
0% {
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-ms-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
-moz-transform: rotate(360deg);
-ms-transform: rotate(360deg);
transform: rotate(360deg);
}
}
.am-weather-sun {
-webkit-animation-name: am-weather-sun;
-moz-animation-name: am-weather-sun;
-ms-animation-name: am-weather-sun;
animation-name: am-weather-sun;
-webkit-animation-duration: 9s;
-moz-animation-duration: 9s;
-ms-animation-duration: 9s;
animation-duration: 9s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
@keyframes am-weather-sun-shiny {
0% {
stroke-dasharray: 3px 10px;
stroke-dashoffset: 0px;
}
50% {
stroke-dasharray: 0.1px 10px;
stroke-dashoffset: -1px;
}
100% {
stroke-dasharray: 3px 10px;
stroke-dashoffset: 0px;
}
}
.am-weather-sun-shiny line {
-webkit-animation-name: am-weather-sun-shiny;
-moz-animation-name: am-weather-sun-shiny;
-ms-animation-name: am-weather-sun-shiny;
animation-name: am-weather-sun-shiny;
-webkit-animation-duration: 2s;
-moz-animation-duration: 2s;
-ms-animation-duration: 2s;
animation-duration: 2s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
]]></style>
</defs>
<g filter="url(#blur)" id="cloudy-day-1">
<g transform="translate(20,10)">
<g transform="translate(0,16)">
<g class="am-weather-sun">
<g>
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(45)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(90)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(135)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(180)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(225)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(270)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(315)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
</g>
<circle cx="0" cy="0" fill="orange" r="5" stroke="orange" stroke-width="2"/>
</g>
<g class="am-weather-cloud-2">
<path d="M47.7,35.4c0-4.6-3.7-8.2-8.2-8.2c-1,0-1.9,0.2-2.8,0.5c-0.3-3.4-3.1-6.2-6.6-6.2c-3.7,0-6.7,3-6.7,6.7c0,0.8,0.2,1.6,0.4,2.3 c-0.3-0.1-0.7-0.1-1-0.1c-3.7,0-6.7,3-6.7,6.7c0,3.6,2.9,6.6,6.5,6.7l17.2,0C44.2,43.3,47.7,39.8,47.7,35.4z" fill="#C6DEFF" stroke="white" stroke-linejoin="round" stroke-width="1.2" transform="translate(-20,-11)"/>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 6.4 KiB

@@ -1,176 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- (c) ammap.com | SVG weather icons -->
<svg
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="64"
height="64"
viewbox="0 0 64 64">
<defs>
<filter id="blur" width="200%" height="200%">
<feGaussianBlur in="SourceAlpha" stdDeviation="3"/>
<feOffset dx="0" dy="4" result="offsetblur"/>
<feComponentTransfer>
<feFuncA type="linear" slope="0.05"/>
</feComponentTransfer>
<feMerge>
<feMergeNode/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
<style type="text/css"><![CDATA[
/*
** CLOUDS
*/
@keyframes am-weather-cloud-2 {
0% {
-webkit-transform: translate(0px,0px);
-moz-transform: translate(0px,0px);
-ms-transform: translate(0px,0px);
transform: translate(0px,0px);
}
50% {
-webkit-transform: translate(2px,0px);
-moz-transform: translate(2px,0px);
-ms-transform: translate(2px,0px);
transform: translate(2px,0px);
}
100% {
-webkit-transform: translate(0px,0px);
-moz-transform: translate(0px,0px);
-ms-transform: translate(0px,0px);
transform: translate(0px,0px);
}
}
.am-weather-cloud-2 {
-webkit-animation-name: am-weather-cloud-2;
-moz-animation-name: am-weather-cloud-2;
animation-name: am-weather-cloud-2;
-webkit-animation-duration: 3s;
-moz-animation-duration: 3s;
animation-duration: 3s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
/*
** SUN
*/
@keyframes am-weather-sun {
0% {
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-ms-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
-moz-transform: rotate(360deg);
-ms-transform: rotate(360deg);
transform: rotate(360deg);
}
}
.am-weather-sun {
-webkit-animation-name: am-weather-sun;
-moz-animation-name: am-weather-sun;
-ms-animation-name: am-weather-sun;
animation-name: am-weather-sun;
-webkit-animation-duration: 9s;
-moz-animation-duration: 9s;
-ms-animation-duration: 9s;
animation-duration: 9s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
@keyframes am-weather-sun-shiny {
0% {
stroke-dasharray: 3px 10px;
stroke-dashoffset: 0px;
}
50% {
stroke-dasharray: 0.1px 10px;
stroke-dashoffset: -1px;
}
100% {
stroke-dasharray: 3px 10px;
stroke-dashoffset: 0px;
}
}
.am-weather-sun-shiny line {
-webkit-animation-name: am-weather-sun-shiny;
-moz-animation-name: am-weather-sun-shiny;
-ms-animation-name: am-weather-sun-shiny;
animation-name: am-weather-sun-shiny;
-webkit-animation-duration: 2s;
-moz-animation-duration: 2s;
-ms-animation-duration: 2s;
animation-duration: 2s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
]]></style>
</defs>
<g filter="url(#blur)" id="cloudy-day-2">
<g transform="translate(20,10)">
<g transform="translate(0,16)">
<g class="am-weather-sun">
<g>
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(45)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(90)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(135)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(180)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(225)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(270)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(315)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
</g>
<circle cx="0" cy="0" fill="orange" r="5" stroke="orange" stroke-width="2"/>
</g>
<g class="am-weather-cloud-2">
<path d="M47.7,35.4c0-4.6-3.7-8.2-8.2-8.2c-1,0-1.9,0.2-2.8,0.5c-0.3-3.4-3.1-6.2-6.6-6.2c-3.7,0-6.7,3-6.7,6.7c0,0.8,0.2,1.6,0.4,2.3 c-0.3-0.1-0.7-0.1-1-0.1c-3.7,0-6.7,3-6.7,6.7c0,3.6,2.9,6.6,6.5,6.7l17.2,0C44.2,43.3,47.7,39.8,47.7,35.4z" fill="#91C0F8" stroke="white" stroke-linejoin="round" stroke-width="1.2" transform="translate(-20,-11)"/>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 6.4 KiB

@@ -1,175 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- (c) ammap.com | SVG weather icons -->
<svg
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="64"
height="64"
viewbox="0 0 64 64">
<defs>
<filter id="blur" width="200%" height="200%">
<feGaussianBlur in="SourceAlpha" stdDeviation="3"/>
<feOffset dx="0" dy="4" result="offsetblur"/>
<feComponentTransfer>
<feFuncA type="linear" slope="0.05"/>
</feComponentTransfer>
<feMerge>
<feMergeNode/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
<style type="text/css"><![CDATA[
/*
** CLOUDS
*/
@keyframes am-weather-cloud-2 {
0% {
-webkit-transform: translate(0px,0px);
-moz-transform: translate(0px,0px);
-ms-transform: translate(0px,0px);
transform: translate(0px,0px);
}
50% {
-webkit-transform: translate(2px,0px);
-moz-transform: translate(2px,0px);
-ms-transform: translate(2px,0px);
transform: translate(2px,0px);
}
100% {
-webkit-transform: translate(0px,0px);
-moz-transform: translate(0px,0px);
-ms-transform: translate(0px,0px);
transform: translate(0px,0px);
}
}
.am-weather-cloud-2 {
-webkit-animation-name: am-weather-cloud-2;
-moz-animation-name: am-weather-cloud-2;
animation-name: am-weather-cloud-2;
-webkit-animation-duration: 3s;
-moz-animation-duration: 3s;
animation-duration: 3s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
/*
** SUN
*/
@keyframes am-weather-sun {
0% {
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-ms-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
-moz-transform: rotate(360deg);
-ms-transform: rotate(360deg);
transform: rotate(360deg);
}
}
.am-weather-sun {
-webkit-animation-name: am-weather-sun;
-moz-animation-name: am-weather-sun;
-ms-animation-name: am-weather-sun;
animation-name: am-weather-sun;
-webkit-animation-duration: 9s;
-moz-animation-duration: 9s;
-ms-animation-duration: 9s;
animation-duration: 9s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
@keyframes am-weather-sun-shiny {
0% {
stroke-dasharray: 3px 10px;
stroke-dashoffset: 0px;
}
50% {
stroke-dasharray: 0.1px 10px;
stroke-dashoffset: -1px;
}
100% {
stroke-dasharray: 3px 10px;
stroke-dashoffset: 0px;
}
}
.am-weather-sun-shiny line {
-webkit-animation-name: am-weather-sun-shiny;
-moz-animation-name: am-weather-sun-shiny;
-ms-animation-name: am-weather-sun-shiny;
animation-name: am-weather-sun-shiny;
-webkit-animation-duration: 2s;
-moz-animation-duration: 2s;
-ms-animation-duration: 2s;
animation-duration: 2s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
]]></style>
</defs>
<g filter="url(#blur)" id="cloudy-day-3">
<g transform="translate(20,10)">
<g transform="translate(0,16)">
<g class="am-weather-sun">
<g>
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(45)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(90)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(135)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(180)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(225)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(270)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(315)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
</g>
<circle cx="0" cy="0" fill="orange" r="5" stroke="orange" stroke-width="2"/>
</g>
<g class="am-weather-cloud-2">
<path d="M47.7,35.4c0-4.6-3.7-8.2-8.2-8.2c-1,0-1.9,0.2-2.8,0.5c-0.3-3.4-3.1-6.2-6.6-6.2c-3.7,0-6.7,3-6.7,6.7c0,0.8,0.2,1.6,0.4,2.3 c-0.3-0.1-0.7-0.1-1-0.1c-3.7,0-6.7,3-6.7,6.7c0,3.6,2.9,6.6,6.5,6.7l17.2,0C44.2,43.3,47.7,39.8,47.7,35.4z" fill="#57A0EE" stroke="white" stroke-linejoin="round" stroke-width="1.2" transform="translate(-20,-11)"/>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 6.4 KiB

@@ -1,198 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- (c) ammap.com | SVG weather icons -->
<svg
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="64"
height="64"
viewbox="0 0 64 64">
<defs>
<filter id="blur" width="200%" height="200%">
<feGaussianBlur in="SourceAlpha" stdDeviation="3"/>
<feOffset dx="0" dy="4" result="offsetblur"/>
<feComponentTransfer>
<feFuncA type="linear" slope="0.05"/>
</feComponentTransfer>
<feMerge>
<feMergeNode/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
<style type="text/css"><![CDATA[
/*
** CLOUDS
*/
@keyframes am-weather-cloud-2 {
0% {
-webkit-transform: translate(0px,0px);
-moz-transform: translate(0px,0px);
-ms-transform: translate(0px,0px);
transform: translate(0px,0px);
}
50% {
-webkit-transform: translate(2px,0px);
-moz-transform: translate(2px,0px);
-ms-transform: translate(2px,0px);
transform: translate(2px,0px);
}
100% {
-webkit-transform: translate(0px,0px);
-moz-transform: translate(0px,0px);
-ms-transform: translate(0px,0px);
transform: translate(0px,0px);
}
}
.am-weather-cloud-2 {
-webkit-animation-name: am-weather-cloud-2;
-moz-animation-name: am-weather-cloud-2;
animation-name: am-weather-cloud-2;
-webkit-animation-duration: 3s;
-moz-animation-duration: 3s;
animation-duration: 3s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
/*
** MOON
*/
@keyframes am-weather-moon {
0% {
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-ms-transform: rotate(0deg);
transform: rotate(0deg);
}
50% {
-webkit-transform: rotate(15deg);
-moz-transform: rotate(15deg);
-ms-transform: rotate(15deg);
transform: rotate(15deg);
}
100% {
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-ms-transform: rotate(0deg);
transform: rotate(0deg);
}
}
.am-weather-moon {
-webkit-animation-name: am-weather-moon;
-moz-animation-name: am-weather-moon;
-ms-animation-name: am-weather-moon;
animation-name: am-weather-moon;
-webkit-animation-duration: 6s;
-moz-animation-duration: 6s;
-ms-animation-duration: 6s;
animation-duration: 6s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
-webkit-transform-origin: 12.5px 15.15px 0; /* TODO FF CENTER ISSUE */
-moz-transform-origin: 12.5px 15.15px 0; /* TODO FF CENTER ISSUE */
-ms-transform-origin: 12.5px 15.15px 0; /* TODO FF CENTER ISSUE */
transform-origin: 12.5px 15.15px 0; /* TODO FF CENTER ISSUE */
}
@keyframes am-weather-moon-star-1 {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
.am-weather-moon-star-1 {
-webkit-animation-name: am-weather-moon-star-1;
-moz-animation-name: am-weather-moon-star-1;
-ms-animation-name: am-weather-moon-star-1;
animation-name: am-weather-moon-star-1;
-webkit-animation-delay: 3s;
-moz-animation-delay: 3s;
-ms-animation-delay: 3s;
animation-delay: 3s;
-webkit-animation-duration: 5s;
-moz-animation-duration: 5s;
-ms-animation-duration: 5s;
animation-duration: 5s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: 1;
-moz-animation-iteration-count: 1;
-ms-animation-iteration-count: 1;
animation-iteration-count: 1;
}
@keyframes am-weather-moon-star-2 {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
.am-weather-moon-star-2 {
-webkit-animation-name: am-weather-moon-star-2;
-moz-animation-name: am-weather-moon-star-2;
-ms-animation-name: am-weather-moon-star-2;
animation-name: am-weather-moon-star-2;
-webkit-animation-delay: 5s;
-moz-animation-delay: 5s;
-ms-animation-delay: 5s;
animation-delay: 5s;
-webkit-animation-duration: 4s;
-moz-animation-duration: 4s;
-ms-animation-duration: 4s;
animation-duration: 4s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: 1;
-moz-animation-iteration-count: 1;
-ms-animation-iteration-count: 1;
animation-iteration-count: 1;
}
]]></style>
</defs>
<g filter="url(#blur)" id="cloudy-night-1">
<g transform="translate(20,10)">
<g transform="translate(16,4), scale(0.8)">
<g class="am-weather-moon-star-1">
<polygon fill="orange" points="3.3,1.5 4,2.7 5.2,3.3 4,4 3.3,5.2 2.7,4 1.5,3.3 2.7,2.7" stroke="none" stroke-miterlimit="10"/>
</g>
<g class="am-weather-moon-star-2">
<polygon fill="orange" points="3.3,1.5 4,2.7 5.2,3.3 4,4 3.3,5.2 2.7,4 1.5,3.3 2.7,2.7" stroke="none" stroke-miterlimit="10" transform="translate(20,10)"/>
</g>
<g class="am-weather-moon">
<path d="M14.5,13.2c0-3.7,2-6.9,5-8.7 c-1.5-0.9-3.2-1.3-5-1.3c-5.5,0-10,4.5-10,10s4.5,10,10,10c1.8,0,3.5-0.5,5-1.3C16.5,20.2,14.5,16.9,14.5,13.2z" fill="orange" stroke="orange" stroke-linejoin="round" stroke-width="2"/>
</g>
</g>
<g class="am-weather-cloud-2">
<path d="M47.7,35.4 c0-4.6-3.7-8.2-8.2-8.2c-1,0-1.9,0.2-2.8,0.5c-0.3-3.4-3.1-6.2-6.6-6.2c-3.7,0-6.7,3-6.7,6.7c0,0.8,0.2,1.6,0.4,2.3 c-0.3-0.1-0.7-0.1-1-0.1c-3.7,0-6.7,3-6.7,6.7c0,3.6,2.9,6.6,6.5,6.7l17.2,0C44.2,43.3,47.7,39.8,47.7,35.4z" fill="#C6DEFF" stroke="white" stroke-linejoin="round" stroke-width="1.2" transform="translate(-20,-11)"/>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 6.5 KiB

@@ -1,198 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- (c) ammap.com | SVG weather icons -->
<svg
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="64"
height="64"
viewbox="0 0 64 64">
<defs>
<filter id="blur" width="200%" height="200%">
<feGaussianBlur in="SourceAlpha" stdDeviation="3"/>
<feOffset dx="0" dy="4" result="offsetblur"/>
<feComponentTransfer>
<feFuncA type="linear" slope="0.05"/>
</feComponentTransfer>
<feMerge>
<feMergeNode/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
<style type="text/css"><![CDATA[
/*
** CLOUDS
*/
@keyframes am-weather-cloud-2 {
0% {
-webkit-transform: translate(0px,0px);
-moz-transform: translate(0px,0px);
-ms-transform: translate(0px,0px);
transform: translate(0px,0px);
}
50% {
-webkit-transform: translate(2px,0px);
-moz-transform: translate(2px,0px);
-ms-transform: translate(2px,0px);
transform: translate(2px,0px);
}
100% {
-webkit-transform: translate(0px,0px);
-moz-transform: translate(0px,0px);
-ms-transform: translate(0px,0px);
transform: translate(0px,0px);
}
}
.am-weather-cloud-2 {
-webkit-animation-name: am-weather-cloud-2;
-moz-animation-name: am-weather-cloud-2;
animation-name: am-weather-cloud-2;
-webkit-animation-duration: 3s;
-moz-animation-duration: 3s;
animation-duration: 3s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
/*
** MOON
*/
@keyframes am-weather-moon {
0% {
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-ms-transform: rotate(0deg);
transform: rotate(0deg);
}
50% {
-webkit-transform: rotate(15deg);
-moz-transform: rotate(15deg);
-ms-transform: rotate(15deg);
transform: rotate(15deg);
}
100% {
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-ms-transform: rotate(0deg);
transform: rotate(0deg);
}
}
.am-weather-moon {
-webkit-animation-name: am-weather-moon;
-moz-animation-name: am-weather-moon;
-ms-animation-name: am-weather-moon;
animation-name: am-weather-moon;
-webkit-animation-duration: 6s;
-moz-animation-duration: 6s;
-ms-animation-duration: 6s;
animation-duration: 6s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
-webkit-transform-origin: 12.5px 15.15px 0; /* TODO FF CENTER ISSUE */
-moz-transform-origin: 12.5px 15.15px 0; /* TODO FF CENTER ISSUE */
-ms-transform-origin: 12.5px 15.15px 0; /* TODO FF CENTER ISSUE */
transform-origin: 12.5px 15.15px 0; /* TODO FF CENTER ISSUE */
}
@keyframes am-weather-moon-star-1 {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
.am-weather-moon-star-1 {
-webkit-animation-name: am-weather-moon-star-1;
-moz-animation-name: am-weather-moon-star-1;
-ms-animation-name: am-weather-moon-star-1;
animation-name: am-weather-moon-star-1;
-webkit-animation-delay: 3s;
-moz-animation-delay: 3s;
-ms-animation-delay: 3s;
animation-delay: 3s;
-webkit-animation-duration: 5s;
-moz-animation-duration: 5s;
-ms-animation-duration: 5s;
animation-duration: 5s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: 1;
-moz-animation-iteration-count: 1;
-ms-animation-iteration-count: 1;
animation-iteration-count: 1;
}
@keyframes am-weather-moon-star-2 {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
.am-weather-moon-star-2 {
-webkit-animation-name: am-weather-moon-star-2;
-moz-animation-name: am-weather-moon-star-2;
-ms-animation-name: am-weather-moon-star-2;
animation-name: am-weather-moon-star-2;
-webkit-animation-delay: 5s;
-moz-animation-delay: 5s;
-ms-animation-delay: 5s;
animation-delay: 5s;
-webkit-animation-duration: 4s;
-moz-animation-duration: 4s;
-ms-animation-duration: 4s;
animation-duration: 4s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: 1;
-moz-animation-iteration-count: 1;
-ms-animation-iteration-count: 1;
animation-iteration-count: 1;
}
]]></style>
</defs>
<g filter="url(#blur)" id="cloudy-night-2">
<g transform="translate(20,10)">
<g transform="translate(16,4), scale(0.8)">
<g class="am-weather-moon-star-1">
<polygon fill="orange" points="3.3,1.5 4,2.7 5.2,3.3 4,4 3.3,5.2 2.7,4 1.5,3.3 2.7,2.7" stroke="none" stroke-miterlimit="10"/>
</g>
<g class="am-weather-moon-star-2">
<polygon fill="orange" points="3.3,1.5 4,2.7 5.2,3.3 4,4 3.3,5.2 2.7,4 1.5,3.3 2.7,2.7" stroke="none" stroke-miterlimit="10" transform="translate(20,10)"/>
</g>
<g class="am-weather-moon">
<path d="M14.5,13.2c0-3.7,2-6.9,5-8.7 c-1.5-0.9-3.2-1.3-5-1.3c-5.5,0-10,4.5-10,10s4.5,10,10,10c1.8,0,3.5-0.5,5-1.3C16.5,20.2,14.5,16.9,14.5,13.2z" fill="orange" stroke="orange" stroke-linejoin="round" stroke-width="2"/>
</g>
</g>
<g class="am-weather-cloud-2">
<path d="M47.7,35.4 c0-4.6-3.7-8.2-8.2-8.2c-1,0-1.9,0.2-2.8,0.5c-0.3-3.4-3.1-6.2-6.6-6.2c-3.7,0-6.7,3-6.7,6.7c0,0.8,0.2,1.6,0.4,2.3 c-0.3-0.1-0.7-0.1-1-0.1c-3.7,0-6.7,3-6.7,6.7c0,3.6,2.9,6.6,6.5,6.7l17.2,0C44.2,43.3,47.7,39.8,47.7,35.4z" fill="#91C0F8" stroke="white" stroke-linejoin="round" stroke-width="1.2" transform="translate(-20,-11)"/>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 6.5 KiB

@@ -1,198 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- (c) ammap.com | SVG weather icons -->
<svg
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="64"
height="64"
viewbox="0 0 64 64">
<defs>
<filter id="blur" width="200%" height="200%">
<feGaussianBlur in="SourceAlpha" stdDeviation="3"/>
<feOffset dx="0" dy="4" result="offsetblur"/>
<feComponentTransfer>
<feFuncA type="linear" slope="0.05"/>
</feComponentTransfer>
<feMerge>
<feMergeNode/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
<style type="text/css"><![CDATA[
/*
** CLOUDS
*/
@keyframes am-weather-cloud-2 {
0% {
-webkit-transform: translate(0px,0px);
-moz-transform: translate(0px,0px);
-ms-transform: translate(0px,0px);
transform: translate(0px,0px);
}
50% {
-webkit-transform: translate(2px,0px);
-moz-transform: translate(2px,0px);
-ms-transform: translate(2px,0px);
transform: translate(2px,0px);
}
100% {
-webkit-transform: translate(0px,0px);
-moz-transform: translate(0px,0px);
-ms-transform: translate(0px,0px);
transform: translate(0px,0px);
}
}
.am-weather-cloud-2 {
-webkit-animation-name: am-weather-cloud-2;
-moz-animation-name: am-weather-cloud-2;
animation-name: am-weather-cloud-2;
-webkit-animation-duration: 3s;
-moz-animation-duration: 3s;
animation-duration: 3s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
/*
** MOON
*/
@keyframes am-weather-moon {
0% {
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-ms-transform: rotate(0deg);
transform: rotate(0deg);
}
50% {
-webkit-transform: rotate(15deg);
-moz-transform: rotate(15deg);
-ms-transform: rotate(15deg);
transform: rotate(15deg);
}
100% {
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-ms-transform: rotate(0deg);
transform: rotate(0deg);
}
}
.am-weather-moon {
-webkit-animation-name: am-weather-moon;
-moz-animation-name: am-weather-moon;
-ms-animation-name: am-weather-moon;
animation-name: am-weather-moon;
-webkit-animation-duration: 6s;
-moz-animation-duration: 6s;
-ms-animation-duration: 6s;
animation-duration: 6s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
-webkit-transform-origin: 12.5px 15.15px 0; /* TODO FF CENTER ISSUE */
-moz-transform-origin: 12.5px 15.15px 0; /* TODO FF CENTER ISSUE */
-ms-transform-origin: 12.5px 15.15px 0; /* TODO FF CENTER ISSUE */
transform-origin: 12.5px 15.15px 0; /* TODO FF CENTER ISSUE */
}
@keyframes am-weather-moon-star-1 {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
.am-weather-moon-star-1 {
-webkit-animation-name: am-weather-moon-star-1;
-moz-animation-name: am-weather-moon-star-1;
-ms-animation-name: am-weather-moon-star-1;
animation-name: am-weather-moon-star-1;
-webkit-animation-delay: 3s;
-moz-animation-delay: 3s;
-ms-animation-delay: 3s;
animation-delay: 3s;
-webkit-animation-duration: 5s;
-moz-animation-duration: 5s;
-ms-animation-duration: 5s;
animation-duration: 5s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: 1;
-moz-animation-iteration-count: 1;
-ms-animation-iteration-count: 1;
animation-iteration-count: 1;
}
@keyframes am-weather-moon-star-2 {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
.am-weather-moon-star-2 {
-webkit-animation-name: am-weather-moon-star-2;
-moz-animation-name: am-weather-moon-star-2;
-ms-animation-name: am-weather-moon-star-2;
animation-name: am-weather-moon-star-2;
-webkit-animation-delay: 5s;
-moz-animation-delay: 5s;
-ms-animation-delay: 5s;
animation-delay: 5s;
-webkit-animation-duration: 4s;
-moz-animation-duration: 4s;
-ms-animation-duration: 4s;
animation-duration: 4s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: 1;
-moz-animation-iteration-count: 1;
-ms-animation-iteration-count: 1;
animation-iteration-count: 1;
}
]]></style>
</defs>
<g filter="url(#blur)" id="cloudy-night-3">
<g transform="translate(20,10)">
<g transform="translate(16,4), scale(0.8)">
<g class="am-weather-moon-star-1">
<polygon fill="orange" points="3.3,1.5 4,2.7 5.2,3.3 4,4 3.3,5.2 2.7,4 1.5,3.3 2.7,2.7" stroke="none" stroke-miterlimit="10"/>
</g>
<g class="am-weather-moon-star-2">
<polygon fill="orange" points="3.3,1.5 4,2.7 5.2,3.3 4,4 3.3,5.2 2.7,4 1.5,3.3 2.7,2.7" stroke="none" stroke-miterlimit="10" transform="translate(20,10)"/>
</g>
<g class="am-weather-moon">
<path d="M14.5,13.2c0-3.7,2-6.9,5-8.7 c-1.5-0.9-3.2-1.3-5-1.3c-5.5,0-10,4.5-10,10s4.5,10,10,10c1.8,0,3.5-0.5,5-1.3C16.5,20.2,14.5,16.9,14.5,13.2z" fill="orange" stroke="orange" stroke-linejoin="round" stroke-width="2"/>
</g>
</g>
<g class="am-weather-cloud-2">
<path d="M47.7,35.4 c0-4.6-3.7-8.2-8.2-8.2c-1,0-1.9,0.2-2.8,0.5c-0.3-3.4-3.1-6.2-6.6-6.2c-3.7,0-6.7,3-6.7,6.7c0,0.8,0.2,1.6,0.4,2.3 c-0.3-0.1-0.7-0.1-1-0.1c-3.7,0-6.7,3-6.7,6.7c0,3.6,2.9,6.6,6.5,6.7l17.2,0C44.2,43.3,47.7,39.8,47.7,35.4z" fill="#57A0EE" stroke="white" stroke-linejoin="round" stroke-width="1.2" transform="translate(-20,-11)"/>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 6.5 KiB

-500
View File
@@ -1,500 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- (c) ammap.com | SVG weather icons -->
<svg
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="64"
height="64"
viewbox="0 0 64 64">
<defs>
<filter id="blur" width="200%" height="200%">
<feGaussianBlur in="SourceAlpha" stdDeviation="3"/>
<feOffset dx="0" dy="4" result="offsetblur"/>
<feComponentTransfer>
<feFuncA type="linear" slope="0.05"/>
</feComponentTransfer>
<feMerge>
<feMergeNode/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
<style type="text/css"><![CDATA[
/*
** CLOUDS
*/
@keyframes am-weather-cloud-1 {
0% {
-webkit-transform: translate(-5px,0px);
-moz-transform: translate(-5px,0px);
-ms-transform: translate(-5px,0px);
transform: translate(-5px,0px);
}
50% {
-webkit-transform: translate(10px,0px);
-moz-transform: translate(10px,0px);
-ms-transform: translate(10px,0px);
transform: translate(10px,0px);
}
100% {
-webkit-transform: translate(-5px,0px);
-moz-transform: translate(-5px,0px);
-ms-transform: translate(-5px,0px);
transform: translate(-5px,0px);
}
}
.am-weather-cloud-1 {
-webkit-animation-name: am-weather-cloud-1;
-moz-animation-name: am-weather-cloud-1;
animation-name: am-weather-cloud-1;
-webkit-animation-duration: 7s;
-moz-animation-duration: 7s;
animation-duration: 7s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
@keyframes am-weather-cloud-2 {
0% {
-webkit-transform: translate(0px,0px);
-moz-transform: translate(0px,0px);
-ms-transform: translate(0px,0px);
transform: translate(0px,0px);
}
50% {
-webkit-transform: translate(2px,0px);
-moz-transform: translate(2px,0px);
-ms-transform: translate(2px,0px);
transform: translate(2px,0px);
}
100% {
-webkit-transform: translate(0px,0px);
-moz-transform: translate(0px,0px);
-ms-transform: translate(0px,0px);
transform: translate(0px,0px);
}
}
.am-weather-cloud-2 {
-webkit-animation-name: am-weather-cloud-2;
-moz-animation-name: am-weather-cloud-2;
animation-name: am-weather-cloud-2;
-webkit-animation-duration: 3s;
-moz-animation-duration: 3s;
animation-duration: 3s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
/*
** SUN
*/
@keyframes am-weather-sun {
0% {
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-ms-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
-moz-transform: rotate(360deg);
-ms-transform: rotate(360deg);
transform: rotate(360deg);
}
}
.am-weather-sun {
-webkit-animation-name: am-weather-sun;
-moz-animation-name: am-weather-sun;
-ms-animation-name: am-weather-sun;
animation-name: am-weather-sun;
-webkit-animation-duration: 9s;
-moz-animation-duration: 9s;
-ms-animation-duration: 9s;
animation-duration: 9s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
@keyframes am-weather-sun-shiny {
0% {
stroke-dasharray: 3px 10px;
stroke-dashoffset: 0px;
}
50% {
stroke-dasharray: 0.1px 10px;
stroke-dashoffset: -1px;
}
100% {
stroke-dasharray: 3px 10px;
stroke-dashoffset: 0px;
}
}
.am-weather-sun-shiny line {
-webkit-animation-name: am-weather-sun-shiny;
-moz-animation-name: am-weather-sun-shiny;
-ms-animation-name: am-weather-sun-shiny;
animation-name: am-weather-sun-shiny;
-webkit-animation-duration: 2s;
-moz-animation-duration: 2s;
-ms-animation-duration: 2s;
animation-duration: 2s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
/*
** MOON
*/
@keyframes am-weather-moon {
0% {
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-ms-transform: rotate(0deg);
transform: rotate(0deg);
}
50% {
-webkit-transform: rotate(15deg);
-moz-transform: rotate(15deg);
-ms-transform: rotate(15deg);
transform: rotate(15deg);
}
100% {
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-ms-transform: rotate(0deg);
transform: rotate(0deg);
}
}
.am-weather-moon {
-webkit-animation-name: am-weather-moon;
-moz-animation-name: am-weather-moon;
-ms-animation-name: am-weather-moon;
animation-name: am-weather-moon;
-webkit-animation-duration: 6s;
-moz-animation-duration: 6s;
-ms-animation-duration: 6s;
animation-duration: 6s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
-webkit-transform-origin: 12.5px 15.15px 0; /* TODO FF CENTER ISSUE */
-moz-transform-origin: 12.5px 15.15px 0; /* TODO FF CENTER ISSUE */
-ms-transform-origin: 12.5px 15.15px 0; /* TODO FF CENTER ISSUE */
transform-origin: 12.5px 15.15px 0; /* TODO FF CENTER ISSUE */
}
@keyframes am-weather-moon-star-1 {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
.am-weather-moon-star-1 {
-webkit-animation-name: am-weather-moon-star-1;
-moz-animation-name: am-weather-moon-star-1;
-ms-animation-name: am-weather-moon-star-1;
animation-name: am-weather-moon-star-1;
-webkit-animation-delay: 3s;
-moz-animation-delay: 3s;
-ms-animation-delay: 3s;
animation-delay: 3s;
-webkit-animation-duration: 5s;
-moz-animation-duration: 5s;
-ms-animation-duration: 5s;
animation-duration: 5s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: 1;
-moz-animation-iteration-count: 1;
-ms-animation-iteration-count: 1;
animation-iteration-count: 1;
}
@keyframes am-weather-moon-star-2 {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
.am-weather-moon-star-2 {
-webkit-animation-name: am-weather-moon-star-2;
-moz-animation-name: am-weather-moon-star-2;
-ms-animation-name: am-weather-moon-star-2;
animation-name: am-weather-moon-star-2;
-webkit-animation-delay: 5s;
-moz-animation-delay: 5s;
-ms-animation-delay: 5s;
animation-delay: 5s;
-webkit-animation-duration: 4s;
-moz-animation-duration: 4s;
-ms-animation-duration: 4s;
animation-duration: 4s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: 1;
-moz-animation-iteration-count: 1;
-ms-animation-iteration-count: 1;
animation-iteration-count: 1;
}
/*
** RAIN
*/
@keyframes am-weather-rain {
0% {
stroke-dashoffset: 0;
}
100% {
stroke-dashoffset: -100;
}
}
.am-weather-rain-1 {
-webkit-animation-name: am-weather-rain;
-moz-animation-name: am-weather-rain;
-ms-animation-name: am-weather-rain;
animation-name: am-weather-rain;
-webkit-animation-duration: 8s;
-moz-animation-duration: 8s;
-ms-animation-duration: 8s;
animation-duration: 8s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
.am-weather-rain-2 {
-webkit-animation-name: am-weather-rain;
-moz-animation-name: am-weather-rain;
-ms-animation-name: am-weather-rain;
animation-name: am-weather-rain;
-webkit-animation-delay: 0.25s;
-moz-animation-delay: 0.25s;
-ms-animation-delay: 0.25s;
animation-delay: 0.25s;
-webkit-animation-duration: 8s;
-moz-animation-duration: 8s;
-ms-animation-duration: 8s;
animation-duration: 8s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
/*
** SNOW
*/
@keyframes am-weather-snow {
0% {
-webkit-transform: translateX(0) translateY(0);
-moz-transform: translateX(0) translateY(0);
-ms-transform: translateX(0) translateY(0);
transform: translateX(0) translateY(0);
}
33.33% {
-webkit-transform: translateX(-1.2px) translateY(2px);
-moz-transform: translateX(-1.2px) translateY(2px);
-ms-transform: translateX(-1.2px) translateY(2px);
transform: translateX(-1.2px) translateY(2px);
}
66.66% {
-webkit-transform: translateX(1.4px) translateY(4px);
-moz-transform: translateX(1.4px) translateY(4px);
-ms-transform: translateX(1.4px) translateY(4px);
transform: translateX(1.4px) translateY(4px);
opacity: 1;
}
100% {
-webkit-transform: translateX(-1.6px) translateY(6px);
-moz-transform: translateX(-1.6px) translateY(6px);
-ms-transform: translateX(-1.6px) translateY(6px);
transform: translateX(-1.6px) translateY(6px);
opacity: 0;
}
}
@keyframes am-weather-snow-reverse {
0% {
-webkit-transform: translateX(0) translateY(0);
-moz-transform: translateX(0) translateY(0);
-ms-transform: translateX(0) translateY(0);
transform: translateX(0) translateY(0);
}
33.33% {
-webkit-transform: translateX(1.2px) translateY(2px);
-moz-transform: translateX(1.2px) translateY(2px);
-ms-transform: translateX(1.2px) translateY(2px);
transform: translateX(1.2px) translateY(2px);
}
66.66% {
-webkit-transform: translateX(-1.4px) translateY(4px);
-moz-transform: translateX(-1.4px) translateY(4px);
-ms-transform: translateX(-1.4px) translateY(4px);
transform: translateX(-1.4px) translateY(4px);
opacity: 1;
}
100% {
-webkit-transform: translateX(1.6px) translateY(6px);
-moz-transform: translateX(1.6px) translateY(6px);
-ms-transform: translateX(1.6px) translateY(6px);
transform: translateX(1.6px) translateY(6px);
opacity: 0;
}
}
.am-weather-snow-1 {
-webkit-animation-name: am-weather-snow;
-moz-animation-name: am-weather-snow;
-ms-animation-name: am-weather-snow;
animation-name: am-weather-snow;
-webkit-animation-duration: 2s;
-moz-animation-duration: 2s;
-ms-animation-duration: 2s;
animation-duration: 2s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
.am-weather-snow-2 {
-webkit-animation-name: am-weather-snow;
-moz-animation-name: am-weather-snow;
-ms-animation-name: am-weather-snow;
animation-name: am-weather-snow;
-webkit-animation-delay: 1.2s;
-moz-animation-delay: 1.2s;
-ms-animation-delay: 1.2s;
animation-delay: 1.2s;
-webkit-animation-duration: 2s;
-moz-animation-duration: 2s;
-ms-animation-duration: 2s;
animation-duration: 2s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
.am-weather-snow-3 {
-webkit-animation-name: am-weather-snow-reverse;
-moz-animation-name: am-weather-snow-reverse;
-ms-animation-name: am-weather-snow-reverse;
animation-name: am-weather-snow-reverse;
-webkit-animation-duration: 2s;
-moz-animation-duration: 2s;
-ms-animation-duration: 2s;
animation-duration: 2s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
/*
** EASING
*/
.am-weather-easing-ease-in-out {
-webkit-animation-timing-function: ease-in-out;
-moz-animation-timing-function: ease-in-out;
-ms-animation-timing-function: ease-in-out;
animation-timing-function: ease-in-out;
}
]]></style>
</defs>
<g filter="url(#blur)" id="cloudy">
<g transform="translate(20,10)">
<g class="am-weather-cloud-1">
<path d="M47.7,35.4 c0-4.6-3.7-8.2-8.2-8.2c-1,0-1.9,0.2-2.8,0.5c-0.3-3.4-3.1-6.2-6.6-6.2c-3.7,0-6.7,3-6.7,6.7c0,0.8,0.2,1.6,0.4,2.3 c-0.3-0.1-0.7-0.1-1-0.1c-3.7,0-6.7,3-6.7,6.7c0,3.6,2.9,6.6,6.5,6.7l17.2,0C44.2,43.3,47.7,39.8,47.7,35.4z" fill="#91C0F8" stroke="white" stroke-linejoin="round" stroke-width="1.2" transform="translate(-10,-8), scale(0.6)"/>
</g>
<g class="am-weather-cloud-2">
<path d="M47.7,35.4 c0-4.6-3.7-8.2-8.2-8.2c-1,0-1.9,0.2-2.8,0.5c-0.3-3.4-3.1-6.2-6.6-6.2c-3.7,0-6.7,3-6.7,6.7c0,0.8,0.2,1.6,0.4,2.3 c-0.3-0.1-0.7-0.1-1-0.1c-3.7,0-6.7,3-6.7,6.7c0,3.6,2.9,6.6,6.5,6.7l17.2,0C44.2,43.3,47.7,39.8,47.7,35.4z" fill="#57A0EE" stroke="white" stroke-linejoin="round" stroke-width="1.2" transform="translate(-20,-11)"/>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 15 KiB

-521
View File
@@ -1,521 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- (c) ammap.com | SVG weather icons -->
<svg
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="64"
height="64"
viewbox="0 0 64 64">
<defs>
<filter id="blur" width="200%" height="200%">
<feGaussianBlur in="SourceAlpha" stdDeviation="3"/>
<feOffset dx="0" dy="4" result="offsetblur"/>
<feComponentTransfer>
<feFuncA type="linear" slope="0.05"/>
</feComponentTransfer>
<feMerge>
<feMergeNode/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
<style type="text/css"><![CDATA[
/*
** CLOUDS
*/
@keyframes am-weather-cloud-1 {
0% {
-webkit-transform: translate(-5px,0px);
-moz-transform: translate(-5px,0px);
-ms-transform: translate(-5px,0px);
transform: translate(-5px,0px);
}
50% {
-webkit-transform: translate(10px,0px);
-moz-transform: translate(10px,0px);
-ms-transform: translate(10px,0px);
transform: translate(10px,0px);
}
100% {
-webkit-transform: translate(-5px,0px);
-moz-transform: translate(-5px,0px);
-ms-transform: translate(-5px,0px);
transform: translate(-5px,0px);
}
}
.am-weather-cloud-1 {
-webkit-animation-name: am-weather-cloud-1;
-moz-animation-name: am-weather-cloud-1;
animation-name: am-weather-cloud-1;
-webkit-animation-duration: 7s;
-moz-animation-duration: 7s;
animation-duration: 7s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
@keyframes am-weather-cloud-2 {
0% {
-webkit-transform: translate(0px,0px);
-moz-transform: translate(0px,0px);
-ms-transform: translate(0px,0px);
transform: translate(0px,0px);
}
50% {
-webkit-transform: translate(2px,0px);
-moz-transform: translate(2px,0px);
-ms-transform: translate(2px,0px);
transform: translate(2px,0px);
}
100% {
-webkit-transform: translate(0px,0px);
-moz-transform: translate(0px,0px);
-ms-transform: translate(0px,0px);
transform: translate(0px,0px);
}
}
.am-weather-cloud-2 {
-webkit-animation-name: am-weather-cloud-2;
-moz-animation-name: am-weather-cloud-2;
animation-name: am-weather-cloud-2;
-webkit-animation-duration: 3s;
-moz-animation-duration: 3s;
animation-duration: 3s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
/*
** SUN
*/
@keyframes am-weather-sun {
0% {
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-ms-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
-moz-transform: rotate(360deg);
-ms-transform: rotate(360deg);
transform: rotate(360deg);
}
}
.am-weather-sun {
-webkit-animation-name: am-weather-sun;
-moz-animation-name: am-weather-sun;
-ms-animation-name: am-weather-sun;
animation-name: am-weather-sun;
-webkit-animation-duration: 9s;
-moz-animation-duration: 9s;
-ms-animation-duration: 9s;
animation-duration: 9s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
@keyframes am-weather-sun-shiny {
0% {
stroke-dasharray: 3px 10px;
stroke-dashoffset: 0px;
}
50% {
stroke-dasharray: 0.1px 10px;
stroke-dashoffset: -1px;
}
100% {
stroke-dasharray: 3px 10px;
stroke-dashoffset: 0px;
}
}
.am-weather-sun-shiny line {
-webkit-animation-name: am-weather-sun-shiny;
-moz-animation-name: am-weather-sun-shiny;
-ms-animation-name: am-weather-sun-shiny;
animation-name: am-weather-sun-shiny;
-webkit-animation-duration: 2s;
-moz-animation-duration: 2s;
-ms-animation-duration: 2s;
animation-duration: 2s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
/*
** MOON
*/
@keyframes am-weather-moon {
0% {
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-ms-transform: rotate(0deg);
transform: rotate(0deg);
}
50% {
-webkit-transform: rotate(15deg);
-moz-transform: rotate(15deg);
-ms-transform: rotate(15deg);
transform: rotate(15deg);
}
100% {
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-ms-transform: rotate(0deg);
transform: rotate(0deg);
}
}
.am-weather-moon {
-webkit-animation-name: am-weather-moon;
-moz-animation-name: am-weather-moon;
-ms-animation-name: am-weather-moon;
animation-name: am-weather-moon;
-webkit-animation-duration: 6s;
-moz-animation-duration: 6s;
-ms-animation-duration: 6s;
animation-duration: 6s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
-webkit-transform-origin: 12.5px 15.15px 0; /* TODO FF CENTER ISSUE */
-moz-transform-origin: 12.5px 15.15px 0; /* TODO FF CENTER ISSUE */
-ms-transform-origin: 12.5px 15.15px 0; /* TODO FF CENTER ISSUE */
transform-origin: 12.5px 15.15px 0; /* TODO FF CENTER ISSUE */
}
@keyframes am-weather-moon-star-1 {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
.am-weather-moon-star-1 {
-webkit-animation-name: am-weather-moon-star-1;
-moz-animation-name: am-weather-moon-star-1;
-ms-animation-name: am-weather-moon-star-1;
animation-name: am-weather-moon-star-1;
-webkit-animation-delay: 3s;
-moz-animation-delay: 3s;
-ms-animation-delay: 3s;
animation-delay: 3s;
-webkit-animation-duration: 5s;
-moz-animation-duration: 5s;
-ms-animation-duration: 5s;
animation-duration: 5s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: 1;
-moz-animation-iteration-count: 1;
-ms-animation-iteration-count: 1;
animation-iteration-count: 1;
}
@keyframes am-weather-moon-star-2 {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
.am-weather-moon-star-2 {
-webkit-animation-name: am-weather-moon-star-2;
-moz-animation-name: am-weather-moon-star-2;
-ms-animation-name: am-weather-moon-star-2;
animation-name: am-weather-moon-star-2;
-webkit-animation-delay: 5s;
-moz-animation-delay: 5s;
-ms-animation-delay: 5s;
animation-delay: 5s;
-webkit-animation-duration: 4s;
-moz-animation-duration: 4s;
-ms-animation-duration: 4s;
animation-duration: 4s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: 1;
-moz-animation-iteration-count: 1;
-ms-animation-iteration-count: 1;
animation-iteration-count: 1;
}
/*
** RAIN
*/
@keyframes am-weather-rain {
0% {
stroke-dashoffset: 0;
}
100% {
stroke-dashoffset: -100;
}
}
.am-weather-rain-1 {
-webkit-animation-name: am-weather-rain;
-moz-animation-name: am-weather-rain;
-ms-animation-name: am-weather-rain;
animation-name: am-weather-rain;
-webkit-animation-duration: 8s;
-moz-animation-duration: 8s;
-ms-animation-duration: 8s;
animation-duration: 8s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
.am-weather-rain-2 {
-webkit-animation-name: am-weather-rain;
-moz-animation-name: am-weather-rain;
-ms-animation-name: am-weather-rain;
animation-name: am-weather-rain;
-webkit-animation-delay: 0.25s;
-moz-animation-delay: 0.25s;
-ms-animation-delay: 0.25s;
animation-delay: 0.25s;
-webkit-animation-duration: 8s;
-moz-animation-duration: 8s;
-ms-animation-duration: 8s;
animation-duration: 8s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
/*
** SNOW
*/
@keyframes am-weather-snow {
0% {
-webkit-transform: translateX(0) translateY(0);
-moz-transform: translateX(0) translateY(0);
-ms-transform: translateX(0) translateY(0);
transform: translateX(0) translateY(0);
}
33.33% {
-webkit-transform: translateX(-1.2px) translateY(2px);
-moz-transform: translateX(-1.2px) translateY(2px);
-ms-transform: translateX(-1.2px) translateY(2px);
transform: translateX(-1.2px) translateY(2px);
}
66.66% {
-webkit-transform: translateX(1.4px) translateY(4px);
-moz-transform: translateX(1.4px) translateY(4px);
-ms-transform: translateX(1.4px) translateY(4px);
transform: translateX(1.4px) translateY(4px);
opacity: 1;
}
100% {
-webkit-transform: translateX(-1.6px) translateY(6px);
-moz-transform: translateX(-1.6px) translateY(6px);
-ms-transform: translateX(-1.6px) translateY(6px);
transform: translateX(-1.6px) translateY(6px);
opacity: 0;
}
}
@keyframes am-weather-snow-reverse {
0% {
-webkit-transform: translateX(0) translateY(0);
-moz-transform: translateX(0) translateY(0);
-ms-transform: translateX(0) translateY(0);
transform: translateX(0) translateY(0);
}
33.33% {
-webkit-transform: translateX(1.2px) translateY(2px);
-moz-transform: translateX(1.2px) translateY(2px);
-ms-transform: translateX(1.2px) translateY(2px);
transform: translateX(1.2px) translateY(2px);
}
66.66% {
-webkit-transform: translateX(-1.4px) translateY(4px);
-moz-transform: translateX(-1.4px) translateY(4px);
-ms-transform: translateX(-1.4px) translateY(4px);
transform: translateX(-1.4px) translateY(4px);
opacity: 1;
}
100% {
-webkit-transform: translateX(1.6px) translateY(6px);
-moz-transform: translateX(1.6px) translateY(6px);
-ms-transform: translateX(1.6px) translateY(6px);
transform: translateX(1.6px) translateY(6px);
opacity: 0;
}
}
.am-weather-snow-1 {
-webkit-animation-name: am-weather-snow;
-moz-animation-name: am-weather-snow;
-ms-animation-name: am-weather-snow;
animation-name: am-weather-snow;
-webkit-animation-duration: 2s;
-moz-animation-duration: 2s;
-ms-animation-duration: 2s;
animation-duration: 2s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
.am-weather-snow-2 {
-webkit-animation-name: am-weather-snow;
-moz-animation-name: am-weather-snow;
-ms-animation-name: am-weather-snow;
animation-name: am-weather-snow;
-webkit-animation-delay: 1.2s;
-moz-animation-delay: 1.2s;
-ms-animation-delay: 1.2s;
animation-delay: 1.2s;
-webkit-animation-duration: 2s;
-moz-animation-duration: 2s;
-ms-animation-duration: 2s;
animation-duration: 2s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
.am-weather-snow-3 {
-webkit-animation-name: am-weather-snow-reverse;
-moz-animation-name: am-weather-snow-reverse;
-ms-animation-name: am-weather-snow-reverse;
animation-name: am-weather-snow-reverse;
-webkit-animation-duration: 2s;
-moz-animation-duration: 2s;
-ms-animation-duration: 2s;
animation-duration: 2s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
/*
** EASING
*/
.am-weather-easing-ease-in-out {
-webkit-animation-timing-function: ease-in-out;
-moz-animation-timing-function: ease-in-out;
-ms-animation-timing-function: ease-in-out;
animation-timing-function: ease-in-out;
}
]]></style>
</defs>
<g filter="url(#blur)" id="day">
<g transform="translate(32,32)">
<g class="am-weather-sun am-weather-sun-shiny am-weather-easing-ease-in-out">
<g>
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3" />
</g>
<g transform="rotate(45)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3" />
</g>
<g transform="rotate(90)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3" />
</g>
<g transform="rotate(135)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3" />
</g>
<g transform="rotate(180)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3" />
</g>
<g transform="rotate(225)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3" />
</g>
<g transform="rotate(270)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3" />
</g>
<g transform="rotate(315)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3" />
</g>
</g>
<circle cx="0" cy="0" fill="orange" r="5" stroke="orange" stroke-width="2"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 16 KiB

-503
View File
@@ -1,503 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- (c) ammap.com | SVG weather icons -->
<svg
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="64"
height="64"
viewbox="0 0 64 64">
<defs>
<filter id="blur" width="200%" height="200%">
<feGaussianBlur in="SourceAlpha" stdDeviation="3"/>
<feOffset dx="0" dy="4" result="offsetblur"/>
<feComponentTransfer>
<feFuncA type="linear" slope="0.05"/>
</feComponentTransfer>
<feMerge>
<feMergeNode/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
<style type="text/css"><![CDATA[
/*
** CLOUDS
*/
@keyframes am-weather-cloud-1 {
0% {
-webkit-transform: translate(-5px,0px);
-moz-transform: translate(-5px,0px);
-ms-transform: translate(-5px,0px);
transform: translate(-5px,0px);
}
50% {
-webkit-transform: translate(10px,0px);
-moz-transform: translate(10px,0px);
-ms-transform: translate(10px,0px);
transform: translate(10px,0px);
}
100% {
-webkit-transform: translate(-5px,0px);
-moz-transform: translate(-5px,0px);
-ms-transform: translate(-5px,0px);
transform: translate(-5px,0px);
}
}
.am-weather-cloud-1 {
-webkit-animation-name: am-weather-cloud-1;
-moz-animation-name: am-weather-cloud-1;
animation-name: am-weather-cloud-1;
-webkit-animation-duration: 7s;
-moz-animation-duration: 7s;
animation-duration: 7s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
@keyframes am-weather-cloud-2 {
0% {
-webkit-transform: translate(0px,0px);
-moz-transform: translate(0px,0px);
-ms-transform: translate(0px,0px);
transform: translate(0px,0px);
}
50% {
-webkit-transform: translate(2px,0px);
-moz-transform: translate(2px,0px);
-ms-transform: translate(2px,0px);
transform: translate(2px,0px);
}
100% {
-webkit-transform: translate(0px,0px);
-moz-transform: translate(0px,0px);
-ms-transform: translate(0px,0px);
transform: translate(0px,0px);
}
}
.am-weather-cloud-2 {
-webkit-animation-name: am-weather-cloud-2;
-moz-animation-name: am-weather-cloud-2;
animation-name: am-weather-cloud-2;
-webkit-animation-duration: 3s;
-moz-animation-duration: 3s;
animation-duration: 3s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
/*
** SUN
*/
@keyframes am-weather-sun {
0% {
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-ms-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
-moz-transform: rotate(360deg);
-ms-transform: rotate(360deg);
transform: rotate(360deg);
}
}
.am-weather-sun {
-webkit-animation-name: am-weather-sun;
-moz-animation-name: am-weather-sun;
-ms-animation-name: am-weather-sun;
animation-name: am-weather-sun;
-webkit-animation-duration: 9s;
-moz-animation-duration: 9s;
-ms-animation-duration: 9s;
animation-duration: 9s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
@keyframes am-weather-sun-shiny {
0% {
stroke-dasharray: 3px 10px;
stroke-dashoffset: 0px;
}
50% {
stroke-dasharray: 0.1px 10px;
stroke-dashoffset: -1px;
}
100% {
stroke-dasharray: 3px 10px;
stroke-dashoffset: 0px;
}
}
.am-weather-sun-shiny line {
-webkit-animation-name: am-weather-sun-shiny;
-moz-animation-name: am-weather-sun-shiny;
-ms-animation-name: am-weather-sun-shiny;
animation-name: am-weather-sun-shiny;
-webkit-animation-duration: 2s;
-moz-animation-duration: 2s;
-ms-animation-duration: 2s;
animation-duration: 2s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
/*
** MOON
*/
@keyframes am-weather-moon {
0% {
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-ms-transform: rotate(0deg);
transform: rotate(0deg);
}
50% {
-webkit-transform: rotate(15deg);
-moz-transform: rotate(15deg);
-ms-transform: rotate(15deg);
transform: rotate(15deg);
}
100% {
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-ms-transform: rotate(0deg);
transform: rotate(0deg);
}
}
.am-weather-moon {
-webkit-animation-name: am-weather-moon;
-moz-animation-name: am-weather-moon;
-ms-animation-name: am-weather-moon;
animation-name: am-weather-moon;
-webkit-animation-duration: 6s;
-moz-animation-duration: 6s;
-ms-animation-duration: 6s;
animation-duration: 6s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
-webkit-transform-origin: 12.5px 15.15px 0; /* TODO FF CENTER ISSUE */
-moz-transform-origin: 12.5px 15.15px 0; /* TODO FF CENTER ISSUE */
-ms-transform-origin: 12.5px 15.15px 0; /* TODO FF CENTER ISSUE */
transform-origin: 12.5px 15.15px 0; /* TODO FF CENTER ISSUE */
}
@keyframes am-weather-moon-star-1 {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
.am-weather-moon-star-1 {
-webkit-animation-name: am-weather-moon-star-1;
-moz-animation-name: am-weather-moon-star-1;
-ms-animation-name: am-weather-moon-star-1;
animation-name: am-weather-moon-star-1;
-webkit-animation-delay: 3s;
-moz-animation-delay: 3s;
-ms-animation-delay: 3s;
animation-delay: 3s;
-webkit-animation-duration: 5s;
-moz-animation-duration: 5s;
-ms-animation-duration: 5s;
animation-duration: 5s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: 1;
-moz-animation-iteration-count: 1;
-ms-animation-iteration-count: 1;
animation-iteration-count: 1;
}
@keyframes am-weather-moon-star-2 {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
.am-weather-moon-star-2 {
-webkit-animation-name: am-weather-moon-star-2;
-moz-animation-name: am-weather-moon-star-2;
-ms-animation-name: am-weather-moon-star-2;
animation-name: am-weather-moon-star-2;
-webkit-animation-delay: 5s;
-moz-animation-delay: 5s;
-ms-animation-delay: 5s;
animation-delay: 5s;
-webkit-animation-duration: 4s;
-moz-animation-duration: 4s;
-ms-animation-duration: 4s;
animation-duration: 4s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: 1;
-moz-animation-iteration-count: 1;
-ms-animation-iteration-count: 1;
animation-iteration-count: 1;
}
/*
** RAIN
*/
@keyframes am-weather-rain {
0% {
stroke-dashoffset: 0;
}
100% {
stroke-dashoffset: -100;
}
}
.am-weather-rain-1 {
-webkit-animation-name: am-weather-rain;
-moz-animation-name: am-weather-rain;
-ms-animation-name: am-weather-rain;
animation-name: am-weather-rain;
-webkit-animation-duration: 8s;
-moz-animation-duration: 8s;
-ms-animation-duration: 8s;
animation-duration: 8s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
.am-weather-rain-2 {
-webkit-animation-name: am-weather-rain;
-moz-animation-name: am-weather-rain;
-ms-animation-name: am-weather-rain;
animation-name: am-weather-rain;
-webkit-animation-delay: 0.25s;
-moz-animation-delay: 0.25s;
-ms-animation-delay: 0.25s;
animation-delay: 0.25s;
-webkit-animation-duration: 8s;
-moz-animation-duration: 8s;
-ms-animation-duration: 8s;
animation-duration: 8s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
/*
** SNOW
*/
@keyframes am-weather-snow {
0% {
-webkit-transform: translateX(0) translateY(0);
-moz-transform: translateX(0) translateY(0);
-ms-transform: translateX(0) translateY(0);
transform: translateX(0) translateY(0);
}
33.33% {
-webkit-transform: translateX(-1.2px) translateY(2px);
-moz-transform: translateX(-1.2px) translateY(2px);
-ms-transform: translateX(-1.2px) translateY(2px);
transform: translateX(-1.2px) translateY(2px);
}
66.66% {
-webkit-transform: translateX(1.4px) translateY(4px);
-moz-transform: translateX(1.4px) translateY(4px);
-ms-transform: translateX(1.4px) translateY(4px);
transform: translateX(1.4px) translateY(4px);
opacity: 1;
}
100% {
-webkit-transform: translateX(-1.6px) translateY(6px);
-moz-transform: translateX(-1.6px) translateY(6px);
-ms-transform: translateX(-1.6px) translateY(6px);
transform: translateX(-1.6px) translateY(6px);
opacity: 0;
}
}
@keyframes am-weather-snow-reverse {
0% {
-webkit-transform: translateX(0) translateY(0);
-moz-transform: translateX(0) translateY(0);
-ms-transform: translateX(0) translateY(0);
transform: translateX(0) translateY(0);
}
33.33% {
-webkit-transform: translateX(1.2px) translateY(2px);
-moz-transform: translateX(1.2px) translateY(2px);
-ms-transform: translateX(1.2px) translateY(2px);
transform: translateX(1.2px) translateY(2px);
}
66.66% {
-webkit-transform: translateX(-1.4px) translateY(4px);
-moz-transform: translateX(-1.4px) translateY(4px);
-ms-transform: translateX(-1.4px) translateY(4px);
transform: translateX(-1.4px) translateY(4px);
opacity: 1;
}
100% {
-webkit-transform: translateX(1.6px) translateY(6px);
-moz-transform: translateX(1.6px) translateY(6px);
-ms-transform: translateX(1.6px) translateY(6px);
transform: translateX(1.6px) translateY(6px);
opacity: 0;
}
}
.am-weather-snow-1 {
-webkit-animation-name: am-weather-snow;
-moz-animation-name: am-weather-snow;
-ms-animation-name: am-weather-snow;
animation-name: am-weather-snow;
-webkit-animation-duration: 2s;
-moz-animation-duration: 2s;
-ms-animation-duration: 2s;
animation-duration: 2s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
.am-weather-snow-2 {
-webkit-animation-name: am-weather-snow;
-moz-animation-name: am-weather-snow;
-ms-animation-name: am-weather-snow;
animation-name: am-weather-snow;
-webkit-animation-delay: 1.2s;
-moz-animation-delay: 1.2s;
-ms-animation-delay: 1.2s;
animation-delay: 1.2s;
-webkit-animation-duration: 2s;
-moz-animation-duration: 2s;
-ms-animation-duration: 2s;
animation-duration: 2s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
.am-weather-snow-3 {
-webkit-animation-name: am-weather-snow-reverse;
-moz-animation-name: am-weather-snow-reverse;
-ms-animation-name: am-weather-snow-reverse;
animation-name: am-weather-snow-reverse;
-webkit-animation-duration: 2s;
-moz-animation-duration: 2s;
-ms-animation-duration: 2s;
animation-duration: 2s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
/*
** EASING
*/
.am-weather-easing-ease-in-out {
-webkit-animation-timing-function: ease-in-out;
-moz-animation-timing-function: ease-in-out;
-ms-animation-timing-function: ease-in-out;
animation-timing-function: ease-in-out;
}
]]></style>
</defs>
<g filter="url(#blur)" id="night">
<g transform="translate(20,20)">
<g class="am-weather-moon-star-1">
<polygon fill="orange" points="3.3,1.5 4,2.7 5.2,3.3 4,4 3.3,5.2 2.7,4 1.5,3.3 2.7,2.7" stroke="none" stroke-miterlimit="10"/>
</g>
<g class="am-weather-moon-star-2">
<polygon fill="orange" points="3.3,1.5 4,2.7 5.2,3.3 4,4 3.3,5.2 2.7,4 1.5,3.3 2.7,2.7" stroke="none" stroke-miterlimit="10" transform="translate(20,10)"/>
</g>
<g class="am-weather-moon">
<path d="M14.5,13.2c0-3.7,2-6.9,5-8.7 c-1.5-0.9-3.2-1.3-5-1.3c-5.5,0-10,4.5-10,10s4.5,10,10,10c1.8,0,3.5-0.5,5-1.3C16.5,20.2,14.5,16.9,14.5,13.2z" fill="orange" stroke="orange" stroke-linejoin="round" stroke-width="2"/>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 15 KiB

@@ -1,157 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- (c) ammap.com | SVG weather icons -->
<svg
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="64"
height="64"
viewbox="0 0 64 64">
<defs>
<filter id="blur" width="200%" height="200%">
<feGaussianBlur in="SourceAlpha" stdDeviation="3"/>
<feOffset dx="0" dy="4" result="offsetblur"/>
<feComponentTransfer>
<feFuncA type="linear" slope="0.05"/>
</feComponentTransfer>
<feMerge>
<feMergeNode/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
<style type="text/css"><![CDATA[
/*
** SUN
*/
@keyframes am-weather-sun {
0% {
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-ms-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
-moz-transform: rotate(360deg);
-ms-transform: rotate(360deg);
transform: rotate(360deg);
}
}
.am-weather-sun {
-webkit-animation-name: am-weather-sun;
-moz-animation-name: am-weather-sun;
-ms-animation-name: am-weather-sun;
animation-name: am-weather-sun;
-webkit-animation-duration: 9s;
-moz-animation-duration: 9s;
-ms-animation-duration: 9s;
animation-duration: 9s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
/*
** RAIN
*/
@keyframes am-weather-rain {
0% {
stroke-dashoffset: 0;
}
100% {
stroke-dashoffset: -100;
}
}
.am-weather-rain-1 {
-webkit-animation-name: am-weather-rain;
-moz-animation-name: am-weather-rain;
-ms-animation-name: am-weather-rain;
animation-name: am-weather-rain;
-webkit-animation-duration: 8s;
-moz-animation-duration: 8s;
-ms-animation-duration: 8s;
animation-duration: 8s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
.am-weather-rain-2 {
-webkit-animation-name: am-weather-rain;
-moz-animation-name: am-weather-rain;
-ms-animation-name: am-weather-rain;
animation-name: am-weather-rain;
-webkit-animation-delay: 0.25s;
-moz-animation-delay: 0.25s;
-ms-animation-delay: 0.25s;
animation-delay: 0.25s;
-webkit-animation-duration: 8s;
-moz-animation-duration: 8s;
-ms-animation-duration: 8s;
animation-duration: 8s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
]]></style>
</defs>
<g filter="url(#blur)" id="rainy-1">
<g transform="translate(20,10)">
<g transform="translate(0,16), scale(1.2)">
<g class="am-weather-sun">
<g>
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(45)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(90)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(135)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(180)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(225)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(270)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(315)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
</g>
<circle cx="0" cy="0" fill="orange" r="5" stroke="orange" stroke-width="2"/>
</g>
<g>
<path d="M47.7,35.4c0-4.6-3.7-8.2-8.2-8.2c-1,0-1.9,0.2-2.8,0.5c-0.3-3.4-3.1-6.2-6.6-6.2c-3.7,0-6.7,3-6.7,6.7c0,0.8,0.2,1.6,0.4,2.3 c-0.3-0.1-0.7-0.1-1-0.1c-3.7,0-6.7,3-6.7,6.7c0,3.6,2.9,6.6,6.5,6.7l17.2,0C44.2,43.3,47.7,39.8,47.7,35.4z" fill="#57A0EE" stroke="white" stroke-linejoin="round" stroke-width="1.5" transform="translate(-15,-5), scale(0.85)"/>
</g>
</g>
<g transform="translate(34,46), rotate(10)">
<line class="am-weather-rain-1" fill="none" stroke="#91C0F8" stroke-dasharray="4,7" stroke-linecap="round" stroke-width="2" transform="translate(-6,1)" x1="0" x2="0" y1="0" y2="8" />
<line class="am-weather-rain-2" fill="none" stroke="#91C0F8" stroke-dasharray="4,7" stroke-linecap="round" stroke-width="2" transform="translate(0,-1)" x1="0" x2="0" y1="0" y2="8" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 6.4 KiB

@@ -1,133 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- (c) ammap.com | SVG weather icons -->
<svg
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="64"
height="64"
viewbox="0 0 64 64">
<defs>
<filter id="blur" width="200%" height="200%">
<feGaussianBlur in="SourceAlpha" stdDeviation="3"/>
<feOffset dx="0" dy="4" result="offsetblur"/>
<feComponentTransfer>
<feFuncA type="linear" slope="0.05"/>
</feComponentTransfer>
<feMerge>
<feMergeNode/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
<style type="text/css"><![CDATA[
/*
** SUN
*/
@keyframes am-weather-sun {
0% {
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-ms-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
-moz-transform: rotate(360deg);
-ms-transform: rotate(360deg);
transform: rotate(360deg);
}
}
.am-weather-sun {
-webkit-animation-name: am-weather-sun;
-moz-animation-name: am-weather-sun;
-ms-animation-name: am-weather-sun;
animation-name: am-weather-sun;
-webkit-animation-duration: 9s;
-moz-animation-duration: 9s;
-ms-animation-duration: 9s;
animation-duration: 9s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
/*
** RAIN
*/
@keyframes am-weather-rain {
0% {
stroke-dashoffset: 0;
}
100% {
stroke-dashoffset: -100;
}
}
.am-weather-rain-1 {
-webkit-animation-name: am-weather-rain;
-moz-animation-name: am-weather-rain;
-ms-animation-name: am-weather-rain;
animation-name: am-weather-rain;
-webkit-animation-duration: 8s;
-moz-animation-duration: 8s;
-ms-animation-duration: 8s;
animation-duration: 8s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
]]></style>
</defs>
<g filter="url(#blur)" id="rainy-2">
<g transform="translate(20,10)">
<g transform="translate(0,16)">
<g class="am-weather-sun">
<g>
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(45)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(90)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(135)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(180)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(225)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(270)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(315)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
</g>
<circle cx="0" cy="0" fill="orange" r="5" stroke="orange" stroke-width="2"/>
</g>
<g>
<path d="M47.7,35.4c0-4.6-3.7-8.2-8.2-8.2c-1,0-1.9,0.2-2.8,0.5c-0.3-3.4-3.1-6.2-6.6-6.2c-3.7,0-6.7,3-6.7,6.7c0,0.8,0.2,1.6,0.4,2.3 c-0.3-0.1-0.7-0.1-1-0.1c-3.7,0-6.7,3-6.7,6.7c0,3.6,2.9,6.6,6.5,6.7l17.2,0C44.2,43.3,47.7,39.8,47.7,35.4z" fill="#57A0EE" stroke="white" stroke-linejoin="round" stroke-width="1.2" transform="translate(-20,-11)"/>
</g>
</g>
<g transform="translate(37,45), rotate(10)">
<line class="am-weather-rain-1" fill="none" stroke="#91C0F8" stroke-dasharray="4,7" stroke-linecap="round" stroke-width="2" transform="translate(-6,1)" x1="0" x2="0" y1="0" y2="8" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 5.3 KiB

@@ -1,157 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- (c) ammap.com | SVG weather icons -->
<svg
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="64"
height="64"
viewbox="0 0 64 64">
<defs>
<filter id="blur" width="200%" height="200%">
<feGaussianBlur in="SourceAlpha" stdDeviation="3"/>
<feOffset dx="0" dy="4" result="offsetblur"/>
<feComponentTransfer>
<feFuncA type="linear" slope="0.05"/>
</feComponentTransfer>
<feMerge>
<feMergeNode/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
<style type="text/css"><![CDATA[
/*
** SUN
*/
@keyframes am-weather-sun {
0% {
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-ms-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
-moz-transform: rotate(360deg);
-ms-transform: rotate(360deg);
transform: rotate(360deg);
}
}
.am-weather-sun {
-webkit-animation-name: am-weather-sun;
-moz-animation-name: am-weather-sun;
-ms-animation-name: am-weather-sun;
animation-name: am-weather-sun;
-webkit-animation-duration: 9s;
-moz-animation-duration: 9s;
-ms-animation-duration: 9s;
animation-duration: 9s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
/*
** RAIN
*/
@keyframes am-weather-rain {
0% {
stroke-dashoffset: 0;
}
100% {
stroke-dashoffset: -100;
}
}
.am-weather-rain-1 {
-webkit-animation-name: am-weather-rain;
-moz-animation-name: am-weather-rain;
-ms-animation-name: am-weather-rain;
animation-name: am-weather-rain;
-webkit-animation-duration: 8s;
-moz-animation-duration: 8s;
-ms-animation-duration: 8s;
animation-duration: 8s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
.am-weather-rain-2 {
-webkit-animation-name: am-weather-rain;
-moz-animation-name: am-weather-rain;
-ms-animation-name: am-weather-rain;
animation-name: am-weather-rain;
-webkit-animation-delay: 0.25s;
-moz-animation-delay: 0.25s;
-ms-animation-delay: 0.25s;
animation-delay: 0.25s;
-webkit-animation-duration: 8s;
-moz-animation-duration: 8s;
-ms-animation-duration: 8s;
animation-duration: 8s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
]]></style>
</defs>
<g filter="url(#blur)" id="rainy-3">
<g transform="translate(20,10)">
<g transform="translate(0,16)">
<g class="am-weather-sun">
<g>
<line fifll="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(45)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(90)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(135)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(180)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(225)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(270)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(315)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
</g>
<circle cx="0" cy="0" fill="orange" r="5" stroke="orange" stroke-width="2"/>
</g>
<g>
<path d="M47.7,35.4c0-4.6-3.7-8.2-8.2-8.2c-1,0-1.9,0.2-2.8,0.5c-0.3-3.4-3.1-6.2-6.6-6.2c-3.7,0-6.7,3-6.7,6.7c0,0.8,0.2,1.6,0.4,2.3 c-0.3-0.1-0.7-0.1-1-0.1c-3.7,0-6.7,3-6.7,6.7c0,3.6,2.9,6.6,6.5,6.7l17.2,0C44.2,43.3,47.7,39.8,47.7,35.4z" fill="#57A0EE" stroke="white" stroke-linejoin="round" stroke-width="1.2" transform="translate(-20,-11)"/>
</g>
</g>
<g transform="translate(34,46), rotate(10)">
<line class="am-weather-rain-1" fill="none" stroke="#91C0F8" stroke-dasharray="4,7" stroke-linecap="round" stroke-width="2" transform="translate(-6,1)" x1="0" x2="0" y1="0" y2="8" />
<line class="am-weather-rain-2" fill="none" stroke="#91C0F8" stroke-dasharray="4,7" stroke-linecap="round" stroke-width="2" transform="translate(0,-1)" x1="0" x2="0" y1="0" y2="8" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 6.3 KiB

@@ -1,66 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- (c) ammap.com | SVG weather icons -->
<svg
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="64"
height="64"
viewbox="0 0 64 64">
<defs>
<filter id="blur" width="200%" height="200%">
<feGaussianBlur in="SourceAlpha" stdDeviation="3"/>
<feOffset dx="0" dy="4" result="offsetblur"/>
<feComponentTransfer>
<feFuncA type="linear" slope="0.05"/>
</feComponentTransfer>
<feMerge>
<feMergeNode/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
<style type="text/css"><![CDATA[
/*
** RAIN
*/
@keyframes am-weather-rain {
0% {
stroke-dashoffset: 0;
}
100% {
stroke-dashoffset: -100;
}
}
.am-weather-rain-1 {
-webkit-animation-name: am-weather-rain;
-moz-animation-name: am-weather-rain;
-ms-animation-name: am-weather-rain;
animation-name: am-weather-rain;
-webkit-animation-duration: 8s;
-moz-animation-duration: 8s;
-ms-animation-duration: 8s;
animation-duration: 8s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
]]></style>
</defs>
<g filter="url(#blur)" id="rainy-4">
<g transform="translate(20,10)">
<g>
<path d="M47.7,35.4c0-4.6-3.7-8.2-8.2-8.2c-1,0-1.9,0.2-2.8,0.5c-0.3-3.4-3.1-6.2-6.6-6.2c-3.7,0-6.7,3-6.7,6.7c0,0.8,0.2,1.6,0.4,2.3 c-0.3-0.1-0.7-0.1-1-0.1c-3.7,0-6.7,3-6.7,6.7c0,3.6,2.9,6.6,6.5,6.7l17.2,0C44.2,43.3,47.7,39.8,47.7,35.4z" fill="#57A0EE" stroke="white" stroke-linejoin="round" stroke-width="1.2" transform="translate(-20,-11)"/>
</g>
</g>
<g transform="translate(37,45), rotate(10)">
<line class="am-weather-rain-1" fill="none" stroke="#91C0F8" stroke-dasharray="4,7" stroke-linecap="round" stroke-width="2" transform="translate(-6,1)" x1="0" x2="0" y1="0" y2="8" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.3 KiB

@@ -1,90 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- (c) ammap.com | SVG weather icons -->
<svg
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="64"
height="64"
viewbox="0 0 64 64">
<defs>
<filter id="blur" width="200%" height="200%">
<feGaussianBlur in="SourceAlpha" stdDeviation="3"/>
<feOffset dx="0" dy="4" result="offsetblur"/>
<feComponentTransfer>
<feFuncA type="linear" slope="0.05"/>
</feComponentTransfer>
<feMerge>
<feMergeNode/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
<style type="text/css"><![CDATA[
/*
** RAIN
*/
@keyframes am-weather-rain {
0% {
stroke-dashoffset: 0;
}
100% {
stroke-dashoffset: -100;
}
}
.am-weather-rain-1 {
-webkit-animation-name: am-weather-rain;
-moz-animation-name: am-weather-rain;
-ms-animation-name: am-weather-rain;
animation-name: am-weather-rain;
-webkit-animation-duration: 8s;
-moz-animation-duration: 8s;
-ms-animation-duration: 8s;
animation-duration: 8s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
.am-weather-rain-2 {
-webkit-animation-name: am-weather-rain;
-moz-animation-name: am-weather-rain;
-ms-animation-name: am-weather-rain;
animation-name: am-weather-rain;
-webkit-animation-delay: 0.25s;
-moz-animation-delay: 0.25s;
-ms-animation-delay: 0.25s;
animation-delay: 0.25s;
-webkit-animation-duration: 8s;
-moz-animation-duration: 8s;
-ms-animation-duration: 8s;
animation-duration: 8s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
]]></style>
</defs>
<g filter="url(#blur)" id="rainy-5">
<g transform="translate(20,10)">
<g>
<path d="M47.7,35.4c0-4.6-3.7-8.2-8.2-8.2c-1,0-1.9,0.2-2.8,0.5c-0.3-3.4-3.1-6.2-6.6-6.2c-3.7,0-6.7,3-6.7,6.7c0,0.8,0.2,1.6,0.4,2.3 c-0.3-0.1-0.7-0.1-1-0.1c-3.7,0-6.7,3-6.7,6.7c0,3.6,2.9,6.6,6.5,6.7l17.2,0C44.2,43.3,47.7,39.8,47.7,35.4z" fill="#57A0EE" stroke="white" stroke-linejoin="round" stroke-width="1.2" transform="translate(-20,-11)"/>
</g>
</g>
<g transform="translate(34,46), rotate(10)">
<line class="am-weather-rain-1" fill="none" stroke="#91C0F8" stroke-dasharray="4,7" stroke-linecap="round" stroke-width="2" transform="translate(-6,1)" x1="0" x2="0" y1="0" y2="8" />
<line class="am-weather-rain-2" fill="none" stroke="#91C0F8" stroke-dasharray="4,7" stroke-linecap="round" stroke-width="2" transform="translate(0,-1)" x1="0" x2="0" y1="0" y2="8" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.3 KiB

@@ -1,91 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- (c) ammap.com | SVG weather icons -->
<svg
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="64"
height="64"
viewbox="0 0 64 64">
<defs>
<filter id="blur" width="200%" height="200%">
<feGaussianBlur in="SourceAlpha" stdDeviation="3"/>
<feOffset dx="0" dy="4" result="offsetblur"/>
<feComponentTransfer>
<feFuncA type="linear" slope="0.05"/>
</feComponentTransfer>
<feMerge>
<feMergeNode/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
<style type="text/css"><![CDATA[
/*
** RAIN
*/
@keyframes am-weather-rain {
0% {
stroke-dashoffset: 0;
}
100% {
stroke-dashoffset: -100;
}
}
.am-weather-rain-1 {
-webkit-animation-name: am-weather-rain;
-moz-animation-name: am-weather-rain;
-ms-animation-name: am-weather-rain;
animation-name: am-weather-rain;
-webkit-animation-duration: 8s;
-moz-animation-duration: 8s;
-ms-animation-duration: 8s;
animation-duration: 8s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
.am-weather-rain-2 {
-webkit-animation-name: am-weather-rain;
-moz-animation-name: am-weather-rain;
-ms-animation-name: am-weather-rain;
animation-name: am-weather-rain;
-webkit-animation-delay: 0.25s;
-moz-animation-delay: 0.25s;
-ms-animation-delay: 0.25s;
animation-delay: 0.25s;
-webkit-animation-duration: 8s;
-moz-animation-duration: 8s;
-ms-animation-duration: 8s;
animation-duration: 8s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
]]></style>
</defs>
<g filter="url(#blur)" id="rainy-6">
<g transform="translate(20,10)">
<g>
<path d="M47.7,35.4c0-4.6-3.7-8.2-8.2-8.2c-1,0-1.9,0.2-2.8,0.5c-0.3-3.4-3.1-6.2-6.6-6.2c-3.7,0-6.7,3-6.7,6.7c0,0.8,0.2,1.6,0.4,2.3 c-0.3-0.1-0.7-0.1-1-0.1c-3.7,0-6.7,3-6.7,6.7c0,3.6,2.9,6.6,6.5,6.7l17.2,0C44.2,43.3,47.7,39.8,47.7,35.4z" fill="#57A0EE" stroke="white" stroke-linejoin="round" stroke-width="1.2" transform="translate(-20,-11)"/>
</g>
</g>
<g transform="translate(31,46), rotate(10)">
<line class="am-weather-rain-1" fill="none" stroke="#91C0F8" stroke-dasharray="4,4" stroke-linecap="round" stroke-width="2" transform="translate(-4,1)" x1="0" x2="0" y1="0" y2="8" />
<line class="am-weather-rain-2" fill="none" stroke="#91C0F8" stroke-dasharray="4,4" stroke-linecap="round" stroke-width="2" transform="translate(0,-1)" x1="0" x2="0" y1="0" y2="8" />
<line class="am-weather-rain-1" fill="none" stroke="#91C0F8" stroke-dasharray="4,4" stroke-linecap="round" stroke-width="2" transform="translate(4,0)" x1="0" x2="0" y1="0" y2="8" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.5 KiB

@@ -1,91 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- (c) ammap.com | SVG weather icons -->
<svg
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="64"
height="64"
viewbox="0 0 64 64">
<defs>
<filter id="blur" width="200%" height="200%">
<feGaussianBlur in="SourceAlpha" stdDeviation="3"/>
<feOffset dx="0" dy="4" result="offsetblur"/>
<feComponentTransfer>
<feFuncA type="linear" slope="0.05"/>
</feComponentTransfer>
<feMerge>
<feMergeNode/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
<style type="text/css"><![CDATA[
/*
** RAIN
*/
@keyframes am-weather-rain {
0% {
stroke-dashoffset: 0;
}
100% {
stroke-dashoffset: -100;
}
}
.am-weather-rain-1 {
-webkit-animation-name: am-weather-rain;
-moz-animation-name: am-weather-rain;
-ms-animation-name: am-weather-rain;
animation-name: am-weather-rain;
-webkit-animation-duration: 8s;
-moz-animation-duration: 8s;
-ms-animation-duration: 8s;
animation-duration: 8s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
.am-weather-rain-2 {
-webkit-animation-name: am-weather-rain;
-moz-animation-name: am-weather-rain;
-ms-animation-name: am-weather-rain;
animation-name: am-weather-rain;
-webkit-animation-delay: 0.25s;
-moz-animation-delay: 0.25s;
-ms-animation-delay: 0.25s;
animation-delay: 0.25s;
-webkit-animation-duration: 8s;
-moz-animation-duration: 8s;
-ms-animation-duration: 8s;
animation-duration: 8s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
]]></style>
</defs>
<g filter="url(#blur)" id="rainy-7">
<g transform="translate(20,10)">
<g>
<path d="M47.7,35.4c0-4.6-3.7-8.2-8.2-8.2c-1,0-1.9,0.2-2.8,0.5c-0.3-3.4-3.1-6.2-6.6-6.2c-3.7,0-6.7,3-6.7,6.7c0,0.8,0.2,1.6,0.4,2.3 c-0.3-0.1-0.7-0.1-1-0.1c-3.7,0-6.7,3-6.7,6.7c0,3.6,2.9,6.6,6.5,6.7l17.2,0C44.2,43.3,47.7,39.8,47.7,35.4z" fill="#57A0EE" stroke="white" stroke-linejoin="round" stroke-width="1.2" transform="translate(-20,-11)"/>
</g>
</g>
<g transform="translate(31,46), rotate(10)">
<line class="am-weather-rain-1" fill="none" stroke="#91C0F8" stroke-dasharray="0.1,7" stroke-linecap="round" stroke-width="3" transform="translate(-5,1)" x1="0" x2="0" y1="0" y2="8" />
<line class="am-weather-rain-2" fill="none" stroke="#91C0F8" stroke-dasharray="0.1,7" stroke-linecap="round" stroke-width="3" transform="translate(0,-1)" x1="0" x2="0" y1="0" y2="8" />
<line class="am-weather-rain-1" fill="none" stroke="#91C0F8" stroke-dasharray="0.1,7" stroke-linecap="round" stroke-width="3" transform="translate(5,0)" x1="0" x2="0" y1="0" y2="8" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.5 KiB

@@ -1,230 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- (c) ammap.com | SVG weather icons -->
<svg
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="64"
height="64"
viewbox="0 0 64 64">
<defs>
<filter id="blur" width="200%" height="200%">
<feGaussianBlur in="SourceAlpha" stdDeviation="3"/>
<feOffset dx="0" dy="4" result="offsetblur"/>
<feComponentTransfer>
<feFuncA type="linear" slope="0.05"/>
</feComponentTransfer>
<feMerge>
<feMergeNode/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
<style type="text/css"><![CDATA[
/*
** SUN
*/
@keyframes am-weather-sun {
0% {
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-ms-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
-moz-transform: rotate(360deg);
-ms-transform: rotate(360deg);
transform: rotate(360deg);
}
}
.am-weather-sun {
-webkit-animation-name: am-weather-sun;
-moz-animation-name: am-weather-sun;
-ms-animation-name: am-weather-sun;
animation-name: am-weather-sun;
-webkit-animation-duration: 9s;
-moz-animation-duration: 9s;
-ms-animation-duration: 9s;
animation-duration: 9s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
@keyframes am-weather-sun-shiny {
0% {
stroke-dasharray: 3px 10px;
stroke-dashoffset: 0px;
}
50% {
stroke-dasharray: 0.1px 10px;
stroke-dashoffset: -1px;
}
100% {
stroke-dasharray: 3px 10px;
stroke-dashoffset: 0px;
}
}
.am-weather-sun-shiny line {
-webkit-animation-name: am-weather-sun-shiny;
-moz-animation-name: am-weather-sun-shiny;
-ms-animation-name: am-weather-sun-shiny;
animation-name: am-weather-sun-shiny;
-webkit-animation-duration: 2s;
-moz-animation-duration: 2s;
-ms-animation-duration: 2s;
animation-duration: 2s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
/*
** SNOW
*/
@keyframes am-weather-snow {
0% {
-webkit-transform: translateX(0) translateY(0);
-moz-transform: translateX(0) translateY(0);
-ms-transform: translateX(0) translateY(0);
transform: translateX(0) translateY(0);
}
33.33% {
-webkit-transform: translateX(-1.2px) translateY(2px);
-moz-transform: translateX(-1.2px) translateY(2px);
-ms-transform: translateX(-1.2px) translateY(2px);
transform: translateX(-1.2px) translateY(2px);
}
66.66% {
-webkit-transform: translateX(1.4px) translateY(4px);
-moz-transform: translateX(1.4px) translateY(4px);
-ms-transform: translateX(1.4px) translateY(4px);
transform: translateX(1.4px) translateY(4px);
opacity: 1;
}
100% {
-webkit-transform: translateX(-1.6px) translateY(6px);
-moz-transform: translateX(-1.6px) translateY(6px);
-ms-transform: translateX(-1.6px) translateY(6px);
transform: translateX(-1.6px) translateY(6px);
opacity: 0;
}
}
.am-weather-snow-1 {
-webkit-animation-name: am-weather-snow;
-moz-animation-name: am-weather-snow;
-ms-animation-name: am-weather-snow;
animation-name: am-weather-snow;
-webkit-animation-duration: 2s;
-moz-animation-duration: 2s;
-ms-animation-duration: 2s;
animation-duration: 2s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
.am-weather-snow-2 {
-webkit-animation-name: am-weather-snow;
-moz-animation-name: am-weather-snow;
-ms-animation-name: am-weather-snow;
animation-name: am-weather-snow;
-webkit-animation-delay: 1.2s;
-moz-animation-delay: 1.2s;
-ms-animation-delay: 1.2s;
animation-delay: 1.2s;
-webkit-animation-duration: 2s;
-moz-animation-duration: 2s;
-ms-animation-duration: 2s;
animation-duration: 2s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
]]></style>
</defs>
<g filter="url(#blur)" id="snowy-1">
<g transform="translate(20,10)">
<g transform="translate(0,16), scale(1.2)">
<g class="am-weather-sun">
<g>
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(45)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(90)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(135)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(180)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(225)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(270)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(315)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
</g>
<circle cx="0" cy="0" fill="orange" r="5" stroke="orange" stroke-width="2"/>
</g>
<g>
<path d="M47.7,35.4c0-4.6-3.7-8.2-8.2-8.2c-1,0-1.9,0.2-2.8,0.5c-0.3-3.4-3.1-6.2-6.6-6.2c-3.7,0-6.7,3-6.7,6.7c0,0.8,0.2,1.6,0.4,2.3 c-0.3-0.1-0.7-0.1-1-0.1c-3.7,0-6.7,3-6.7,6.7c0,3.6,2.9,6.6,6.5,6.7l17.2,0C44.2,43.3,47.7,39.8,47.7,35.4z" fill="#57A0EE" stroke="white" stroke-linejoin="round" stroke-width="1.5" transform="translate(-15,-5), scale(0.85)"/>
</g>
</g>
<g transform="translate(20,9)">
<g class="am-weather-snow-1">
<g transform="translate(7,28)">
<line fill="none" stroke="#57A0EE" stroke-linecap="round" stroke-width="1.2" transform="translate(0,9), rotate(0)" x1="0" x2="0" y1="-2.5" y2="2.5" />
<line fill="none" stroke="#57A0EE" stroke-linecap="round" stroke-width="1" transform="translate(0,9), rotate(45)" x1="0" x2="0" y1="-2.5" y2="2.5" />
<line fill="none" stroke="#57A0EE" stroke-linecap="round" stroke-width="1" transform="translate(0,9), rotate(90)" x1="0" x2="0" y1="-2.5" y2="2.5" />
<line fill="none" stroke="#57A0EE" stroke-linecap="round" stroke-width="1" transform="translate(0,9), rotate(135)" x1="0" x2="0" y1="-2.5" y2="2.5" />
</g>
</g>
<g class="am-weather-snow-2">
<g transform="translate(16,28)">
<line fill="none" stroke="#57A0EE" stroke-linecap="round" stroke-width="1.2" transform="translate(0,9), rotate(0)" x1="0" x2="0" y1="-2.5" y2="2.5" />
<line fill="none" stroke="#57A0EE" stroke-linecap="round" stroke-width="1" transform="translate(0,9), rotate(45)" x1="0" x2="0" y1="-2.5" y2="2.5" />
<line fill="none" stroke="#57A0EE" stroke-linecap="round" stroke-width="1" transform="translate(0,9), rotate(90)" x1="0" x2="0" y1="-2.5" y2="2.5" />
<line fill="none" stroke="#57A0EE" stroke-linecap="round" stroke-width="1" transform="translate(0,9), rotate(135)" x1="0" x2="0" y1="-2.5" y2="2.5" />
</g>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 9.4 KiB

@@ -1,237 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- (c) ammap.com | SVG weather icons -->
<svg
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="64"
height="64"
viewbox="0 0 64 64">
<defs>
<filter id="blur" width="200%" height="200%">
<feGaussianBlur in="SourceAlpha" stdDeviation="3"/>
<feOffset dx="0" dy="4" result="offsetblur"/>
<feComponentTransfer>
<feFuncA type="linear" slope="0.05"/>
</feComponentTransfer>
<feMerge>
<feMergeNode/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
<style type="text/css"><![CDATA[
/*
** CLOUDS
*/
@keyframes am-weather-cloud-2 {
0% {
-webkit-transform: translate(0px,0px);
-moz-transform: translate(0px,0px);
-ms-transform: translate(0px,0px);
transform: translate(0px,0px);
}
50% {
-webkit-transform: translate(2px,0px);
-moz-transform: translate(2px,0px);
-ms-transform: translate(2px,0px);
transform: translate(2px,0px);
}
100% {
-webkit-transform: translate(0px,0px);
-moz-transform: translate(0px,0px);
-ms-transform: translate(0px,0px);
transform: translate(0px,0px);
}
}
.am-weather-cloud-2 {
-webkit-animation-name: am-weather-cloud-2;
-moz-animation-name: am-weather-cloud-2;
animation-name: am-weather-cloud-2;
-webkit-animation-duration: 3s;
-moz-animation-duration: 3s;
animation-duration: 3s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
/*
** SUN
*/
@keyframes am-weather-sun {
0% {
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-ms-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
-moz-transform: rotate(360deg);
-ms-transform: rotate(360deg);
transform: rotate(360deg);
}
}
.am-weather-sun {
-webkit-animation-name: am-weather-sun;
-moz-animation-name: am-weather-sun;
-ms-animation-name: am-weather-sun;
animation-name: am-weather-sun;
-webkit-animation-duration: 9s;
-moz-animation-duration: 9s;
-ms-animation-duration: 9s;
animation-duration: 9s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
@keyframes am-weather-sun-shiny {
0% {
stroke-dasharray: 3px 10px;
stroke-dashoffset: 0px;
}
50% {
stroke-dasharray: 0.1px 10px;
stroke-dashoffset: -1px;
}
100% {
stroke-dasharray: 3px 10px;
stroke-dashoffset: 0px;
}
}
.am-weather-sun-shiny line {
-webkit-animation-name: am-weather-sun-shiny;
-moz-animation-name: am-weather-sun-shiny;
-ms-animation-name: am-weather-sun-shiny;
animation-name: am-weather-sun-shiny;
-webkit-animation-duration: 2s;
-moz-animation-duration: 2s;
-ms-animation-duration: 2s;
animation-duration: 2s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
/*
** SNOW
*/
@keyframes am-weather-snow {
0% {
-webkit-transform: translateX(0) translateY(0);
-moz-transform: translateX(0) translateY(0);
-ms-transform: translateX(0) translateY(0);
transform: translateX(0) translateY(0);
}
33.33% {
-webkit-transform: translateX(-1.2px) translateY(2px);
-moz-transform: translateX(-1.2px) translateY(2px);
-ms-transform: translateX(-1.2px) translateY(2px);
transform: translateX(-1.2px) translateY(2px);
}
66.66% {
-webkit-transform: translateX(1.4px) translateY(4px);
-moz-transform: translateX(1.4px) translateY(4px);
-ms-transform: translateX(1.4px) translateY(4px);
transform: translateX(1.4px) translateY(4px);
opacity: 1;
}
100% {
-webkit-transform: translateX(-1.6px) translateY(6px);
-moz-transform: translateX(-1.6px) translateY(6px);
-ms-transform: translateX(-1.6px) translateY(6px);
transform: translateX(-1.6px) translateY(6px);
opacity: 0;
}
}
.am-weather-snow-1 {
-webkit-animation-name: am-weather-snow;
-moz-animation-name: am-weather-snow;
-ms-animation-name: am-weather-snow;
animation-name: am-weather-snow;
-webkit-animation-duration: 2s;
-moz-animation-duration: 2s;
-ms-animation-duration: 2s;
animation-duration: 2s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
]]></style>
</defs>
<g filter="url(#blur)" id="snowy-2">
<g transform="translate(20,10)">
<g transform="translate(0,16)">
<g class="am-weather-sun">
<g>
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(45)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(90)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(135)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(180)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(225)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(270)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(315)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
</g>
<circle cx="0" cy="0" fill="orange" r="5" stroke="orange" stroke-width="2"/>
</g>
<g class="am-weather-cloud-2">
<path d="M47.7,35.4c0-4.6-3.7-8.2-8.2-8.2c-1,0-1.9,0.2-2.8,0.5c-0.3-3.4-3.1-6.2-6.6-6.2c-3.7,0-6.7,3-6.7,6.7c0,0.8,0.2,1.6,0.4,2.3 c-0.3-0.1-0.7-0.1-1-0.1c-3.7,0-6.7,3-6.7,6.7c0,3.6,2.9,6.6,6.5,6.7l17.2,0C44.2,43.3,47.7,39.8,47.7,35.4z" fill="#57A0EE" stroke="white" stroke-linejoin="round" stroke-width="1.2" transform="translate(-20,-11)"/>
</g>
</g>
<g class="am-weather-snow-1">
<g transform="translate(32,38)">
<line fill="none" stroke="#57A0EE" stroke-linecap="round" stroke-width="1.2" transform="translate(0,9), rotate(0)" x1="0" x2="0" y1="-2.5" y2="2.5" />
<line fill="none" stroke="#57A0EE" stroke-linecap="round" stroke-width="1" transform="translate(0,9), rotate(45)" x1="0" x2="0" y1="-2.5" y2="2.5" />
<line fill="none" stroke="#57A0EE" stroke-linecap="round" stroke-width="1" transform="translate(0,9), rotate(90)" x1="0" x2="0" y1="-2.5" y2="2.5" />
<line fill="none" stroke="#57A0EE" stroke-linecap="round" stroke-width="1" transform="translate(0,9), rotate(135)" x1="0" x2="0" y1="-2.5" y2="2.5" />
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 8.8 KiB

@@ -1,268 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- (c) ammap.com | SVG weather icons -->
<svg
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="64"
height="64"
viewbox="0 0 64 64">
<defs>
<filter id="blur" width="200%" height="200%">
<feGaussianBlur in="SourceAlpha" stdDeviation="3"/>
<feOffset dx="0" dy="4" result="offsetblur"/>
<feComponentTransfer>
<feFuncA type="linear" slope="0.05"/>
</feComponentTransfer>
<feMerge>
<feMergeNode/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
<style type="text/css"><![CDATA[
/*
** CLOUDS
*/
@keyframes am-weather-cloud-2 {
0% {
-webkit-transform: translate(0px,0px);
-moz-transform: translate(0px,0px);
-ms-transform: translate(0px,0px);
transform: translate(0px,0px);
}
50% {
-webkit-transform: translate(2px,0px);
-moz-transform: translate(2px,0px);
-ms-transform: translate(2px,0px);
transform: translate(2px,0px);
}
100% {
-webkit-transform: translate(0px,0px);
-moz-transform: translate(0px,0px);
-ms-transform: translate(0px,0px);
transform: translate(0px,0px);
}
}
.am-weather-cloud-2 {
-webkit-animation-name: am-weather-cloud-2;
-moz-animation-name: am-weather-cloud-2;
animation-name: am-weather-cloud-2;
-webkit-animation-duration: 3s;
-moz-animation-duration: 3s;
animation-duration: 3s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
/*
** SUN
*/
@keyframes am-weather-sun {
0% {
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-ms-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
-moz-transform: rotate(360deg);
-ms-transform: rotate(360deg);
transform: rotate(360deg);
}
}
.am-weather-sun {
-webkit-animation-name: am-weather-sun;
-moz-animation-name: am-weather-sun;
-ms-animation-name: am-weather-sun;
animation-name: am-weather-sun;
-webkit-animation-duration: 9s;
-moz-animation-duration: 9s;
-ms-animation-duration: 9s;
animation-duration: 9s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
@keyframes am-weather-sun-shiny {
0% {
stroke-dasharray: 3px 10px;
stroke-dashoffset: 0px;
}
50% {
stroke-dasharray: 0.1px 10px;
stroke-dashoffset: -1px;
}
100% {
stroke-dasharray: 3px 10px;
stroke-dashoffset: 0px;
}
}
.am-weather-sun-shiny line {
-webkit-animation-name: am-weather-sun-shiny;
-moz-animation-name: am-weather-sun-shiny;
-ms-animation-name: am-weather-sun-shiny;
animation-name: am-weather-sun-shiny;
-webkit-animation-duration: 2s;
-moz-animation-duration: 2s;
-ms-animation-duration: 2s;
animation-duration: 2s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
/*
** SNOW
*/
@keyframes am-weather-snow {
0% {
-webkit-transform: translateX(0) translateY(0);
-moz-transform: translateX(0) translateY(0);
-ms-transform: translateX(0) translateY(0);
transform: translateX(0) translateY(0);
}
33.33% {
-webkit-transform: translateX(-1.2px) translateY(2px);
-moz-transform: translateX(-1.2px) translateY(2px);
-ms-transform: translateX(-1.2px) translateY(2px);
transform: translateX(-1.2px) translateY(2px);
}
66.66% {
-webkit-transform: translateX(1.4px) translateY(4px);
-moz-transform: translateX(1.4px) translateY(4px);
-ms-transform: translateX(1.4px) translateY(4px);
transform: translateX(1.4px) translateY(4px);
opacity: 1;
}
100% {
-webkit-transform: translateX(-1.6px) translateY(6px);
-moz-transform: translateX(-1.6px) translateY(6px);
-ms-transform: translateX(-1.6px) translateY(6px);
transform: translateX(-1.6px) translateY(6px);
opacity: 0;
}
}
.am-weather-snow-1 {
-webkit-animation-name: am-weather-snow;
-moz-animation-name: am-weather-snow;
-ms-animation-name: am-weather-snow;
animation-name: am-weather-snow;
-webkit-animation-duration: 2s;
-moz-animation-duration: 2s;
-ms-animation-duration: 2s;
animation-duration: 2s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
.am-weather-snow-2 {
-webkit-animation-name: am-weather-snow;
-moz-animation-name: am-weather-snow;
-ms-animation-name: am-weather-snow;
animation-name: am-weather-snow;
-webkit-animation-delay: 1.2s;
-moz-animation-delay: 1.2s;
-ms-animation-delay: 1.2s;
animation-delay: 1.2s;
-webkit-animation-duration: 2s;
-moz-animation-duration: 2s;
-ms-animation-duration: 2s;
animation-duration: 2s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
]]></style>
</defs>
<g filter="url(#blur)" id="snowy-3">
<g transform="translate(20,10)">
<g transform="translate(0,16)">
<g class="am-weather-sun">
<g>
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(45)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(90)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(135)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(180)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(225)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(270)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
<g transform="rotate(315)">
<line fill="none" stroke="orange" stroke-linecap="round" stroke-width="2" transform="translate(0,9)" x1="0" x2="0" y1="0" y2="3"/>
</g>
</g>
<circle cx="0" cy="0" fill="orange" r="5" stroke="orange" stroke-width="2"/>
</g>
<g>
<path d="M47.7,35.4c0-4.6-3.7-8.2-8.2-8.2c-1,0-1.9,0.2-2.8,0.5c-0.3-3.4-3.1-6.2-6.6-6.2c-3.7,0-6.7,3-6.7,6.7c0,0.8,0.2,1.6,0.4,2.3 c-0.3-0.1-0.7-0.1-1-0.1c-3.7,0-6.7,3-6.7,6.7c0,3.6,2.9,6.6,6.5,6.7l17.2,0C44.2,43.3,47.7,39.8,47.7,35.4z" fill="#57A0EE" stroke="white" stroke-linejoin="round" stroke-width="1.2" transform="translate(-20,-11)"/>
</g>
<g class="am-weather-snow-1">
<g transform="translate(7,28)">
<line fill="none" stroke="#57A0EE" stroke-linecap="round" stroke-width="1.2" transform="translate(0,9), rotate(0)" x1="0" x2="0" y1="-2.5" y2="2.5" />
<line fill="none" stroke="#57A0EE" stroke-linecap="round" stroke-width="1" transform="translate(0,9), rotate(45)" x1="0" x2="0" y1="-2.5" y2="2.5" />
<line fill="none" stroke="#57A0EE" stroke-linecap="round" stroke-width="1" transform="translate(0,9), rotate(90)" x1="0" x2="0" y1="-2.5" y2="2.5" />
<line fill="none" stroke="#57A0EE" stroke-linecap="round" stroke-width="1" transform="translate(0,9), rotate(135)" x1="0" x2="0" y1="-2.5" y2="2.5" />
</g>
</g>
<g class="am-weather-snow-2">
<g transform="translate(16,28)">
<line fill="none" stroke="#57A0EE" stroke-linecap="round" stroke-width="1.2" transform="translate(0,9), rotate(0)" x1="0" x2="0" y1="-2.5" y2="2.5" />
<line fill="none" stroke="#57A0EE" stroke-linecap="round" stroke-width="1" transform="translate(0,9), rotate(45)" x1="0" x2="0" y1="-2.5" y2="2.5" />
<line fill="none" stroke="#57A0EE" stroke-linecap="round" stroke-width="1" transform="translate(0,9), rotate(90)" x1="0" x2="0" y1="-2.5" y2="2.5" />
<line fill="none" stroke="#57A0EE" stroke-linecap="round" stroke-width="1" transform="translate(0,9), rotate(135)" x1="0" x2="0" y1="-2.5" y2="2.5" />
</g>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 10 KiB

@@ -1,94 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- (c) ammap.com | SVG weather icons -->
<svg
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="64"
height="64"
viewbox="0 0 64 64">
<defs>
<filter id="blur" width="200%" height="200%">
<feGaussianBlur in="SourceAlpha" stdDeviation="3"/>
<feOffset dx="0" dy="4" result="offsetblur"/>
<feComponentTransfer>
<feFuncA type="linear" slope="0.05"/>
</feComponentTransfer>
<feMerge>
<feMergeNode/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
<style type="text/css"><![CDATA[
/*
** SNOW
*/
@keyframes am-weather-snow {
0% {
-webkit-transform: translate(0.0px,0);
-moz-transform: translate(0.0px,0);
-ms-transform: translate(0.0px,0);
transform: translate(0.0px,0);
}
33.33% {
-webkit-transform: translate(-1.2px,2px);
-moz-transform: translate(-1.2px,2px);
-ms-transform: translate(-1.2px,2px);
transform: translate(-1.2px,2px);
}
66.66% {
-webkit-transform: translate(1.4px,4px);
-moz-transform: translate(1.4px,4px);
-ms-transform: translate(1.4px,4px);
transform: translate(1.4px,4px);
opacity: 1;
}
100% {
-webkit-transform: translate(-1.6px,6px);
-moz-transform: translate(-1.6px,6px);
-ms-transform: translate(-1.6px,6px);
transform: translate(-1.6px,6px);
opacity: 0;
}
}
.am-weather-snow-1 {
-webkit-animation-name: am-weather-snow;
-moz-animation-name: am-weather-snow;
-ms-animation-name: am-weather-snow;
animation-name: am-weather-snow;
-webkit-animation-duration: 2s;
-moz-animation-duration: 2s;
-ms-animation-duration: 2s;
animation-duration: 2s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
]]></style>
</defs>
<g filter="url(#blur)" id="snowy-4">
<g transform="translate(20,10)">
<g>
<path d="M47.7,35.4c0-4.6-3.7-8.2-8.2-8.2c-1,0-1.9,0.2-2.8,0.5c-0.3-3.4-3.1-6.2-6.6-6.2c-3.7,0-6.7,3-6.7,6.7c0,0.8,0.2,1.6,0.4,2.3 c-0.3-0.1-0.7-0.1-1-0.1c-3.7,0-6.7,3-6.7,6.7c0,3.6,2.9,6.6,6.5,6.7l17.2,0C44.2,43.3,47.7,39.8,47.7,35.4z" fill="#57A0EE" stroke="white" stroke-linejoin="round" stroke-width="1.2" transform="translate(-20,-11)"/>
</g>
<g class="am-weather-snow-1">
<g transform="translate(11,28)">
<line fill="none" stroke="#57A0EE" stroke-linecap="round" stroke-width="1.2" transform="translate(0,9), rotate(0)" x1="0" x2="0" y1="-2.5" y2="2.5" />
<line fill="none" stroke="#57A0EE" stroke-linecap="round" stroke-width="1" transform="translate(0,9), rotate(45)" x1="0" x2="0" y1="-2.5" y2="2.5" />
<line fill="none" stroke="#57A0EE" stroke-linecap="round" stroke-width="1" transform="translate(0,9), rotate(90)" x1="0" x2="0" y1="-2.5" y2="2.5" />
<line fill="none" stroke="#57A0EE" stroke-linecap="round" stroke-width="1" transform="translate(0,9), rotate(135)" x1="0" x2="0" y1="-2.5" y2="2.5" />
</g>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.6 KiB

@@ -1,166 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- (c) ammap.com | SVG weather icons -->
<svg
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="64"
height="64"
viewbox="0 0 64 64">
<defs>
<filter id="blur" width="200%" height="200%">
<feGaussianBlur in="SourceAlpha" stdDeviation="3"/>
<feOffset dx="0" dy="4" result="offsetblur"/>
<feComponentTransfer>
<feFuncA type="linear" slope="0.05"/>
</feComponentTransfer>
<feMerge>
<feMergeNode/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
<style type="text/css"><![CDATA[
/*
** CLOUDS
*/
@keyframes am-weather-cloud-2 {
0% {
-webkit-transform: translate(0px,0px);
-moz-transform: translate(0px,0px);
-ms-transform: translate(0px,0px);
transform: translate(0px,0px);
}
50% {
-webkit-transform: translate(2px,0px);
-moz-transform: translate(2px,0px);
-ms-transform: translate(2px,0px);
transform: translate(2px,0px);
}
100% {
-webkit-transform: translate(0px,0px);
-moz-transform: translate(0px,0px);
-ms-transform: translate(0px,0px);
transform: translate(0px,0px);
}
}
.am-weather-cloud-2 {
-webkit-animation-name: am-weather-cloud-2;
-moz-animation-name: am-weather-cloud-2;
animation-name: am-weather-cloud-2;
-webkit-animation-duration: 3s;
-moz-animation-duration: 3s;
animation-duration: 3s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
/*
** SNOW
*/
@keyframes am-weather-snow {
0% {
-webkit-transform: translateX(0) translateY(0);
-moz-transform: translateX(0) translateY(0);
-ms-transform: translateX(0) translateY(0);
transform: translateX(0) translateY(0);
}
33.33% {
-webkit-transform: translateX(-1.2px) translateY(2px);
-moz-transform: translateX(-1.2px) translateY(2px);
-ms-transform: translateX(-1.2px) translateY(2px);
transform: translateX(-1.2px) translateY(2px);
}
66.66% {
-webkit-transform: translateX(1.4px) translateY(4px);
-moz-transform: translateX(1.4px) translateY(4px);
-ms-transform: translateX(1.4px) translateY(4px);
transform: translateX(1.4px) translateY(4px);
opacity: 1;
}
100% {
-webkit-transform: translateX(-1.6px) translateY(6px);
-moz-transform: translateX(-1.6px) translateY(6px);
-ms-transform: translateX(-1.6px) translateY(6px);
transform: translateX(-1.6px) translateY(6px);
opacity: 0;
}
}
.am-weather-snow-1 {
-webkit-animation-name: am-weather-snow;
-moz-animation-name: am-weather-snow;
-ms-animation-name: am-weather-snow;
animation-name: am-weather-snow;
-webkit-animation-duration: 2s;
-moz-animation-duration: 2s;
-ms-animation-duration: 2s;
animation-duration: 2s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
.am-weather-snow-2 {
-webkit-animation-name: am-weather-snow;
-moz-animation-name: am-weather-snow;
-ms-animation-name: am-weather-snow;
animation-name: am-weather-snow;
-webkit-animation-delay: 1.2s;
-moz-animation-delay: 1.2s;
-ms-animation-delay: 1.2s;
animation-delay: 1.2s;
-webkit-animation-duration: 2s;
-moz-animation-duration: 2s;
-ms-animation-duration: 2s;
animation-duration: 2s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
]]></style>
</defs>
<g filter="url(#blur)" id="snowy-5">
<g transform="translate(20,10)">
<g class="am-weather-cloud-2">
<path d="M47.7,35.4c0-4.6-3.7-8.2-8.2-8.2c-1,0-1.9,0.2-2.8,0.5c-0.3-3.4-3.1-6.2-6.6-6.2c-3.7,0-6.7,3-6.7,6.7c0,0.8,0.2,1.6,0.4,2.3 c-0.3-0.1-0.7-0.1-1-0.1c-3.7,0-6.7,3-6.7,6.7c0,3.6,2.9,6.6,6.5,6.7l17.2,0C44.2,43.3,47.7,39.8,47.7,35.4z" fill="#57A0EE" stroke="white" stroke-linejoin="round" stroke-width="1.2" transform="translate(-20,-11)"/>
</g>
<g class="am-weather-snow-1">
<g transform="translate(7,28)">
<line fill="none" stroke="#57A0EE" stroke-linecap="round" stroke-width="1.2" transform="translate(0,9), rotate(0)" x1="0" x2="0" y1="-2.5" y2="2.5" />
<line fill="none" stroke="#57A0EE" stroke-linecap="round" stroke-width="1" transform="translate(0,9), rotate(45)" x1="0" x2="0" y1="-2.5" y2="2.5" />
<line fill="none" stroke="#57A0EE" stroke-linecap="round" stroke-width="1" transform="translate(0,9), rotate(90)" x1="0" x2="0" y1="-2.5" y2="2.5" />
<line fill="none" stroke="#57A0EE" stroke-linecap="round" stroke-width="1" transform="translate(0,9), rotate(135)" x1="0" x2="0" y1="-2.5" y2="2.5" />
</g>
</g>
<g class="am-weather-snow-2">
<g transform="translate(16,28)">
<line fill="none" stroke="#57A0EE" stroke-linecap="round" stroke-width="1.2" transform="translate(0,9), rotate(0)" x1="0" x2="0" y1="-2.5" y2="2.5" />
<line fill="none" stroke="#57A0EE" stroke-linecap="round" stroke-width="1" transform="translate(0,9), rotate(45)" x1="0" x2="0" y1="-2.5" y2="2.5" />
<line fill="none" stroke="#57A0EE" stroke-linecap="round" stroke-width="1" transform="translate(0,9), rotate(90)" x1="0" x2="0" y1="-2.5" y2="2.5" />
<line fill="none" stroke="#57A0EE" stroke-linecap="round" stroke-width="1" transform="translate(0,9), rotate(135)" x1="0" x2="0" y1="-2.5" y2="2.5" />
</g>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 6.5 KiB

@@ -1,225 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- (c) ammap.com | SVG weather icons -->
<svg
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="64"
height="64"
viewbox="0 0 64 64">
<defs>
<filter id="blur" width="200%" height="200%">
<feGaussianBlur in="SourceAlpha" stdDeviation="3"/>
<feOffset dx="0" dy="4" result="offsetblur"/>
<feComponentTransfer>
<feFuncA type="linear" slope="0.05"/>
</feComponentTransfer>
<feMerge>
<feMergeNode/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
<style type="text/css"><![CDATA[
/*
** CLOUDS
*/
@keyframes am-weather-cloud-2 {
0% {
-webkit-transform: translate(0px,0px);
-moz-transform: translate(0px,0px);
-ms-transform: translate(0px,0px);
transform: translate(0px,0px);
}
50% {
-webkit-transform: translate(2px,0px);
-moz-transform: translate(2px,0px);
-ms-transform: translate(2px,0px);
transform: translate(2px,0px);
}
100% {
-webkit-transform: translate(0px,0px);
-moz-transform: translate(0px,0px);
-ms-transform: translate(0px,0px);
transform: translate(0px,0px);
}
}
.am-weather-cloud-2 {
-webkit-animation-name: am-weather-cloud-2;
-moz-animation-name: am-weather-cloud-2;
animation-name: am-weather-cloud-2;
-webkit-animation-duration: 3s;
-moz-animation-duration: 3s;
animation-duration: 3s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
/*
** SNOW
*/
@keyframes am-weather-snow {
0% {
-webkit-transform: translateX(0) translateY(0);
-moz-transform: translateX(0) translateY(0);
-ms-transform: translateX(0) translateY(0);
transform: translateX(0) translateY(0);
}
33.33% {
-webkit-transform: translateX(-1.2px) translateY(2px);
-moz-transform: translateX(-1.2px) translateY(2px);
-ms-transform: translateX(-1.2px) translateY(2px);
transform: translateX(-1.2px) translateY(2px);
}
66.66% {
-webkit-transform: translateX(1.4px) translateY(4px);
-moz-transform: translateX(1.4px) translateY(4px);
-ms-transform: translateX(1.4px) translateY(4px);
transform: translateX(1.4px) translateY(4px);
opacity: 1;
}
100% {
-webkit-transform: translateX(-1.6px) translateY(6px);
-moz-transform: translateX(-1.6px) translateY(6px);
-ms-transform: translateX(-1.6px) translateY(6px);
transform: translateX(-1.6px) translateY(6px);
opacity: 0;
}
}
@keyframes am-weather-snow-reverse {
0% {
-webkit-transform: translateX(0) translateY(0);
-moz-transform: translateX(0) translateY(0);
-ms-transform: translateX(0) translateY(0);
transform: translateX(0) translateY(0);
}
33.33% {
-webkit-transform: translateX(1.2px) translateY(2px);
-moz-transform: translateX(1.2px) translateY(2px);
-ms-transform: translateX(1.2px) translateY(2px);
transform: translateX(1.2px) translateY(2px);
}
66.66% {
-webkit-transform: translateX(-1.4px) translateY(4px);
-moz-transform: translateX(-1.4px) translateY(4px);
-ms-transform: translateX(-1.4px) translateY(4px);
transform: translateX(-1.4px) translateY(4px);
opacity: 1;
}
100% {
-webkit-transform: translateX(1.6px) translateY(6px);
-moz-transform: translateX(1.6px) translateY(6px);
-ms-transform: translateX(1.6px) translateY(6px);
transform: translateX(1.6px) translateY(6px);
opacity: 0;
}
}
.am-weather-snow-1 {
-webkit-animation-name: am-weather-snow;
-moz-animation-name: am-weather-snow;
-ms-animation-name: am-weather-snow;
animation-name: am-weather-snow;
-webkit-animation-duration: 2s;
-moz-animation-duration: 2s;
-ms-animation-duration: 2s;
animation-duration: 2s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
.am-weather-snow-2 {
-webkit-animation-name: am-weather-snow;
-moz-animation-name: am-weather-snow;
-ms-animation-name: am-weather-snow;
animation-name: am-weather-snow;
-webkit-animation-delay: 1.2s;
-moz-animation-delay: 1.2s;
-ms-animation-delay: 1.2s;
animation-delay: 1.2s;
-webkit-animation-duration: 2s;
-moz-animation-duration: 2s;
-ms-animation-duration: 2s;
animation-duration: 2s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
.am-weather-snow-3 {
-webkit-animation-name: am-weather-snow-reverse;
-moz-animation-name: am-weather-snow-reverse;
-ms-animation-name: am-weather-snow-reverse;
animation-name: am-weather-snow-reverse;
-webkit-animation-duration: 2s;
-moz-animation-duration: 2s;
-ms-animation-duration: 2s;
animation-duration: 2s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
-ms-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
]]></style>
</defs>
<g filter="url(#blur)" id="snowy-6">
<g transform="translate(20,10)">
<g class="am-weather-cloud-2">
<path d="M47.7,35.4c0-4.6-3.7-8.2-8.2-8.2c-1,0-1.9,0.2-2.8,0.5c-0.3-3.4-3.1-6.2-6.6-6.2c-3.7,0-6.7,3-6.7,6.7c0,0.8,0.2,1.6,0.4,2.3 c-0.3-0.1-0.7-0.1-1-0.1c-3.7,0-6.7,3-6.7,6.7c0,3.6,2.9,6.6,6.5,6.7l17.2,0C44.2,43.3,47.7,39.8,47.7,35.4z" fill="#57A0EE" stroke="white" stroke-linejoin="round" stroke-width="1.2" transform="translate(-20,-11)"/>
</g>
<g class="am-weather-snow-1">
<g transform="translate(3,28)">
<line fill="none" stroke="#57A0EE" stroke-linecap="round" stroke-width="1.2" transform="translate(0,9), rotate(0)" x1="0" x2="0" y1="-2.5" y2="2.5" />
<line fill="none" stroke="#57A0EE" stroke-linecap="round" stroke-width="1" transform="translate(0,9), rotate(45)" x1="0" x2="0" y1="-2.5" y2="2.5" />
<line fill="none" stroke="#57A0EE" stroke-linecap="round" stroke-width="1" transform="translate(0,9), rotate(90)" x1="0" x2="0" y1="-2.5" y2="2.5" />
<line fill="none" stroke="#57A0EE" stroke-linecap="round" stroke-width="1" transform="translate(0,9), rotate(135)" x1="0" x2="0" y1="-2.5" y2="2.5" />
</g>
</g>
<g class="am-weather-snow-2">
<g transform="translate(11,28)">
<line fill="none" stroke="#57A0EE" stroke-linecap="round" stroke-width="1.2" transform="translate(0,9), rotate(0)" x1="0" x2="0" y1="-2.5" y2="2.5" />
<line fill="none" stroke="#57A0EE" stroke-linecap="round" stroke-width="1" transform="translate(0,9), rotate(45)" x1="0" x2="0" y1="-2.5" y2="2.5" />
<line fill="none" stroke="#57A0EE" stroke-linecap="round" stroke-width="1" transform="translate(0,9), rotate(90)" x1="0" x2="0" y1="-2.5" y2="2.5" />
<line fill="none" stroke="#57A0EE" stroke-linecap="round" stroke-width="1" transform="translate(0,9), rotate(135)" x1="0" x2="0" y1="-2.5" y2="2.5" />
</g>
</g>
<g class="am-weather-snow-3">
<g transform="translate(20,28)">
<line fill="none" stroke="#57A0EE" stroke-linecap="round" stroke-width="1.2" transform="translate(0,9), rotate(0)" x1="0" x2="0" y1="-2.5" y2="2.5" />
<line fill="none" stroke="#57A0EE" stroke-linecap="round" stroke-width="1" transform="translate(0,9), rotate(45)" x1="0" x2="0" y1="-2.5" y2="2.5" />
<line fill="none" stroke="#57A0EE" stroke-linecap="round" stroke-width="1" transform="translate(0,9), rotate(90)" x1="0" x2="0" y1="-2.5" y2="2.5" />
<line fill="none" stroke="#57A0EE" stroke-linecap="round" stroke-width="1" transform="translate(0,9), rotate(135)" x1="0" x2="0" y1="-2.5" y2="2.5" />
</g>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 9.0 KiB

@@ -1,268 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- (c) ammap.com | SVG weather icons -->
<svg
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="64"
height="64"
viewbox="0 0 64 64">
<defs>
<filter id="blur" width="200%" height="200%">
<feGaussianBlur in="SourceAlpha" stdDeviation="3"/>
<feOffset dx="0" dy="4" result="offsetblur"/>
<feComponentTransfer>
<feFuncA type="linear" slope="0.05"/>
</feComponentTransfer>
<feMerge>
<feMergeNode/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
<style type="text/css"><![CDATA[
/*
** CLOUDS
*/
@keyframes am-weather-cloud-1 {
0% {
-webkit-transform: translate(-5px,0px);
-moz-transform: translate(-5px,0px);
-ms-transform: translate(-5px,0px);
transform: translate(-5px,0px);
}
50% {
-webkit-transform: translate(10px,0px);
-moz-transform: translate(10px,0px);
-ms-transform: translate(10px,0px);
transform: translate(10px,0px);
}
100% {
-webkit-transform: translate(-5px,0px);
-moz-transform: translate(-5px,0px);
-ms-transform: translate(-5px,0px);
transform: translate(-5px,0px);
}
}
.am-weather-cloud-1 {
-webkit-animation-name: am-weather-cloud-1;
-moz-animation-name: am-weather-cloud-1;
animation-name: am-weather-cloud-1;
-webkit-animation-duration: 7s;
-moz-animation-duration: 7s;
animation-duration: 7s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
@keyframes am-weather-cloud-2 {
0% {
-webkit-transform: translate(0px,0px);
-moz-transform: translate(0px,0px);
-ms-transform: translate(0px,0px);
transform: translate(0px,0px);
}
50% {
-webkit-transform: translate(2px,0px);
-moz-transform: translate(2px,0px);
-ms-transform: translate(2px,0px);
transform: translate(2px,0px);
}
100% {
-webkit-transform: translate(0px,0px);
-moz-transform: translate(0px,0px);
-ms-transform: translate(0px,0px);
transform: translate(0px,0px);
}
}
.am-weather-cloud-2 {
-webkit-animation-name: am-weather-cloud-2;
-moz-animation-name: am-weather-cloud-2;
animation-name: am-weather-cloud-2;
-webkit-animation-duration: 3s;
-moz-animation-duration: 3s;
animation-duration: 3s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
/*
** STROKE
*/
@keyframes am-weather-stroke {
0% {
-webkit-transform: translate(0.0px,0.0px);
-moz-transform: translate(0.0px,0.0px);
-ms-transform: translate(0.0px,0.0px);
transform: translate(0.0px,0.0px);
}
2% {
-webkit-transform: translate(0.3px,0.0px);
-moz-transform: translate(0.3px,0.0px);
-ms-transform: translate(0.3px,0.0px);
transform: translate(0.3px,0.0px);
}
4% {
-webkit-transform: translate(0.0px,0.0px);
-moz-transform: translate(0.0px,0.0px);
-ms-transform: translate(0.0px,0.0px);
transform: translate(0.0px,0.0px);
}
6% {
-webkit-transform: translate(0.5px,0.4px);
-moz-transform: translate(0.5px,0.4px);
-ms-transform: translate(0.5px,0.4px);
transform: translate(0.5px,0.4px);
}
8% {
-webkit-transform: translate(0.0px,0.0px);
-moz-transform: translate(0.0px,0.0px);
-ms-transform: translate(0.0px,0.0px);
transform: translate(0.0px,0.0px);
}
10% {
-webkit-transform: translate(0.3px,0.0px);
-moz-transform: translate(0.3px,0.0px);
-ms-transform: translate(0.3px,0.0px);
transform: translate(0.3px,0.0px);
}
12% {
-webkit-transform: translate(0.0px,0.0px);
-moz-transform: translate(0.0px,0.0px);
-ms-transform: translate(0.0px,0.0px);
transform: translate(0.0px,0.0px);
}
14% {
-webkit-transform: translate(0.3px,0.0px);
-moz-transform: translate(0.3px,0.0px);
-ms-transform: translate(0.3px,0.0px);
transform: translate(0.3px,0.0px);
}
16% {
-webkit-transform: translate(0.0px,0.0px);
-moz-transform: translate(0.0px,0.0px);
-ms-transform: translate(0.0px,0.0px);
transform: translate(0.0px,0.0px);
}
18% {
-webkit-transform: translate(0.3px,0.0px);
-moz-transform: translate(0.3px,0.0px);
-ms-transform: translate(0.3px,0.0px);
transform: translate(0.3px,0.0px);
}
20% {
-webkit-transform: translate(0.0px,0.0px);
-moz-transform: translate(0.0px,0.0px);
-ms-transform: translate(0.0px,0.0px);
transform: translate(0.0px,0.0px);
}
22% {
-webkit-transform: translate(1px,0.0px);
-moz-transform: translate(1px,0.0px);
-ms-transform: translate(1px,0.0px);
transform: translate(1px,0.0px);
}
24% {
-webkit-transform: translate(0.0px,0.0px);
-moz-transform: translate(0.0px,0.0px);
-ms-transform: translate(0.0px,0.0px);
transform: translate(0.0px,0.0px);
}
26% {
-webkit-transform: translate(-1px,0.0px);
-moz-transform: translate(-1px,0.0px);
-ms-transform: translate(-1px,0.0px);
transform: translate(-1px,0.0px);
}
28% {
-webkit-transform: translate(0.0px,0.0px);
-moz-transform: translate(0.0px,0.0px);
-ms-transform: translate(0.0px,0.0px);
transform: translate(0.0px,0.0px);
}
40% {
fill: orange;
-webkit-transform: translate(0.0px,0.0px);
-moz-transform: translate(0.0px,0.0px);
-ms-transform: translate(0.0px,0.0px);
transform: translate(0.0px,0.0px);
}
65% {
fill: white;
-webkit-transform: translate(-1px,5.0px);
-moz-transform: translate(-1px,5.0px);
-ms-transform: translate(-1px,5.0px);
transform: translate(-1px,5.0px);
}
61% {
fill: orange;
}
100% {
-webkit-transform: translate(0.0px,0.0px);
-moz-transform: translate(0.0px,0.0px);
-ms-transform: translate(0.0px,0.0px);
transform: translate(0.0px,0.0px);
}
}
.am-weather-stroke {
-webkit-animation-name: am-weather-stroke;
-moz-animation-name: am-weather-stroke;
animation-name: am-weather-stroke;
-webkit-animation-duration: 1.11s;
-moz-animation-duration: 1.11s;
animation-duration: 1.11s;
-webkit-animation-timing-function: linear;
-moz-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
]]></style>
</defs>
<g filter="url(#blur)" id="thunder">
<g transform="translate(20,10)">
<g class="am-weather-cloud-1">
<path d="M47.7,35.4 c0-4.6-3.7-8.2-8.2-8.2c-1,0-1.9,0.2-2.8,0.5c-0.3-3.4-3.1-6.2-6.6-6.2c-3.7,0-6.7,3-6.7,6.7c0,0.8,0.2,1.6,0.4,2.3 c-0.3-0.1-0.7-0.1-1-0.1c-3.7,0-6.7,3-6.7,6.7c0,3.6,2.9,6.6,6.5,6.7l17.2,0C44.2,43.3,47.7,39.8,47.7,35.4z" fill="#91C0F8" stroke="white" stroke-linejoin="round" stroke-width="1.2" transform="translate(-10,-6), scale(0.6)" />
</g>
<g>
<path d="M47.7,35.4 c0-4.6-3.7-8.2-8.2-8.2c-1,0-1.9,0.2-2.8,0.5c-0.3-3.4-3.1-6.2-6.6-6.2c-3.7,0-6.7,3-6.7,6.7c0,0.8,0.2,1.6,0.4,2.3 c-0.3-0.1-0.7-0.1-1-0.1c-3.7,0-6.7,3-6.7,6.7c0,3.6,2.9,6.6,6.5,6.7l17.2,0C44.2,43.3,47.7,39.8,47.7,35.4z" fill="#57A0EE" stroke="white" stroke-linejoin="round" stroke-width="1.2" transform="translate(-20,-11)" />
</g>
<g transform="translate(-9,28), scale(1.2)">
<polygon class="am-weather-stroke" fill="orange" stroke="white" stroke-width="1" points="14.3,-2.9 20.5,-2.9 16.4,4.3 20.3,4.3 11.5,14.6 14.9,6.9 11.1,6.9" />
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 8.3 KiB

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 65 KiB

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 64 KiB

@@ -1,9 +0,0 @@
<svg width="21px" height="17px" viewBox="187 110 21 17" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 3.8.3 (29802) - http://www.bohemiancoding.com/sketch -->
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Wind" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" transform="translate(197.611216, 118.415064) rotate(-30.000000) translate(-197.611216, -118.415064) translate(189.111216, 115.915064)" stroke-linecap="round">
<path d="M0.5,2.5 L13,2.5" id="Line" stroke="#000000"></path>
<polygon id="Triangle-1" stroke="#000000" stroke-linejoin="round" fill="#000000" points="13 5 13 1.13686838e-13 17 2.5"></polygon>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 752 B

@@ -1,14 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="64px" height="64px" viewBox="0 0 64 64" enable-background="new 0 0 64 64" xml:space="preserve">
<line fill="none" stroke="#000000" stroke-width="2" stroke-miterlimit="10" x1="0" y1="47" x2="64" y2="47"/>
<line fill="none" stroke="#000000" stroke-width="2" stroke-miterlimit="10" x1="10" y1="37" x2="0" y2="37"/>
<line fill="none" stroke="#000000" stroke-width="2" stroke-miterlimit="10" x1="64" y1="37" x2="54" y2="37"/>
<line fill="none" stroke="#000000" stroke-width="2" stroke-miterlimit="10" x1="32" y1="15" x2="32" y2="4"/>
<line fill="none" stroke="#000000" stroke-width="2" stroke-miterlimit="10" x1="14" y1="23" x2="6" y2="15"/>
<line fill="none" stroke="#000000" stroke-width="2" stroke-miterlimit="10" x1="50" y1="23" x2="58" y2="15"/>
<path fill="#000000" stroke="#000000" stroke-width="2" stroke-miterlimit="10" d="M48.159,47C49.96,44.096,51,40.669,51,37
c0-10.493-8.506-19-19-19s-19,8.507-19,19c0,3.668,1.04,7.094,2.841,9.998"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

@@ -1,216 +0,0 @@
const fireEvent = (node, type, detail, options) => {
options = options || {};
detail = detail === null || detail === undefined ? {} : detail;
const event = new Event(type, {
bubbles: options.bubbles === undefined ? true : options.bubbles,
cancelable: Boolean(options.cancelable),
composed: options.composed === undefined ? true : options.composed,
});
event.detail = detail;
node.dispatchEvent(event);
return event;
};
if (
!customElements.get("ha-switch") &&
customElements.get("paper-toggle-button")
) {
customElements.define("ha-switch", customElements.get("paper-toggle-button"));
}
const LitElement = customElements.get("hui-masonry-view") ? Object.getPrototypeOf(customElements.get("hui-masonry-view")) : Object.getPrototypeOf(customElements.get("hui-view"));
const html = LitElement.prototype.html;
const css = LitElement.prototype.css;
const HELPERS = window.loadCardHelpers();
export class WeatherCardEditor extends LitElement {
setConfig(config) {
this._config = { ...config };
}
static get properties() {
return { hass: {}, _config: {} };
}
get _entity() {
return this._config.entity || "";
}
get _name() {
return this._config.name || "";
}
get _icons() {
return this._config.icons || "";
}
get _current() {
return this._config.current !== false;
}
get _details() {
return this._config.details !== false;
}
get _forecast() {
return this._config.forecast !== false;
}
get _hourly_forecast() {
return this._config.hourly_forecast !== false;
}
get _number_of_forecasts() {
return this._config.number_of_forecasts || 5;
}
firstUpdated() {
HELPERS.then(help => {
if (help.importMoreInfoControl) {
help.importMoreInfoControl("fan");
}
})
}
render() {
if (!this.hass) {
return html``;
}
const entities = Object.keys(this.hass.states).filter(
(eid) => eid.substr(0, eid.indexOf(".")) === "weather"
);
return html`
<div class="card-config">
<div>
<paper-input
label="Name"
.value="${this._name}"
.configValue="${"name"}"
@value-changed="${this._valueChanged}"
></paper-input>
<paper-input
label="Icons location"
.value="${this._icons}"
.configValue="${"icons"}"
@value-changed="${this._valueChanged}"
></paper-input>
${customElements.get("ha-entity-picker")
? html`
<ha-entity-picker
.hass="${this.hass}"
.value="${this._entity}"
.configValue=${"entity"}
domain-filter="weather"
@change="${this._valueChanged}"
allow-custom-entity
></ha-entity-picker>
`
: html`
<paper-dropdown-menu
label="Entity"
@value-changed="${this._valueChanged}"
.configValue="${"entity"}"
>
<paper-listbox
slot="dropdown-content"
.selected="${entities.indexOf(this._entity)}"
>
${entities.map((entity) => {
return html` <paper-item>${entity}</paper-item> `;
})}
</paper-listbox>
</paper-dropdown-menu>
`}
<div class="switches">
<div class="switch">
<ha-switch
.checked=${this._current}
.configValue="${"current"}"
@change="${this._valueChanged}"
></ha-switch
><span>Show current</span>
</div>
<div class="switch">
<ha-switch
.checked=${this._details}
.configValue="${"details"}"
@change="${this._valueChanged}"
></ha-switch
><span>Show details</span>
</div>
<div class="switch">
<ha-switch
.checked=${this._forecast}
.configValue="${"forecast"}"
@change="${this._valueChanged}"
></ha-switch
><span>Show forecast</span>
</div>
<div class="switch">
<ha-switch
.checked=${this._hourly_forecast}
.configValue="${"hourly_forecast"}"
@change="${this._valueChanged}"
></ha-switch
><span>Show hourly forecast</span>
</div>
</div>
<paper-input
label="Number of future forcasts"
type="number"
min="1"
max="8"
value=${this._number_of_forecasts}
.configValue="${"number_of_forecasts"}"
@value-changed="${this._valueChanged}"
></paper-input>
</div>
</div>
`;
}
_valueChanged(ev) {
if (!this._config || !this.hass) {
return;
}
const target = ev.target;
if (this[`_${target.configValue}`] === target.value) {
return;
}
if (target.configValue) {
if (target.value === "") {
delete this._config[target.configValue];
} else {
this._config = {
...this._config,
[target.configValue]:
target.checked !== undefined ? target.checked : target.value,
};
}
}
fireEvent(this, "config-changed", { config: this._config });
}
static get styles() {
return css`
.switches {
margin: 8px 0;
display: flex;
justify-content: space-between;
}
.switch {
display: flex;
align-items: center;
justify-items: center;
}
.switches span {
padding: 0 16px;
}
`;
}
}
customElements.define("weather-card-editor", WeatherCardEditor);
-530
View File
@@ -1,530 +0,0 @@
const LitElement = customElements.get("hui-masonry-view") ? Object.getPrototypeOf(customElements.get("hui-masonry-view")) : Object.getPrototypeOf(customElements.get("hui-view"));
const html = LitElement.prototype.html;
const css = LitElement.prototype.css;
const weatherIconsDay = {
clear: "day",
"clear-night": "night",
cloudy: "cloudy",
fog: "cloudy",
hail: "rainy-7",
lightning: "thunder",
"lightning-rainy": "thunder",
partlycloudy: "cloudy-day-3",
pouring: "rainy-6",
rainy: "rainy-5",
snowy: "snowy-6",
"snowy-rainy": "rainy-7",
sunny: "day",
windy: "cloudy",
"windy-variant": "cloudy-day-3",
exceptional: "!!",
};
const weatherIconsNight = {
...weatherIconsDay,
clear: "night",
sunny: "night",
partlycloudy: "cloudy-night-3",
"windy-variant": "cloudy-night-3",
};
const windDirections = [
"N",
"NNE",
"NE",
"ENE",
"E",
"ESE",
"SE",
"SSE",
"S",
"SSW",
"SW",
"WSW",
"W",
"WNW",
"NW",
"NNW",
"N",
];
window.customCards = window.customCards || [];
window.customCards.push({
type: "weather-card",
name: "Weather Card",
description: "A custom weather card with animated icons.",
preview: true,
documentationURL: "https://github.com/bramkragten/weather-card",
});
const fireEvent = (node, type, detail, options) => {
options = options || {};
detail = detail === null || detail === undefined ? {} : detail;
const event = new Event(type, {
bubbles: options.bubbles === undefined ? true : options.bubbles,
cancelable: Boolean(options.cancelable),
composed: options.composed === undefined ? true : options.composed,
});
event.detail = detail;
node.dispatchEvent(event);
return event;
};
function hasConfigOrEntityChanged(element, changedProps) {
if (changedProps.has("_config")) {
return true;
}
const oldHass = changedProps.get("hass");
if (oldHass) {
return (
oldHass.states[element._config.entity] !==
element.hass.states[element._config.entity] ||
oldHass.states["sun.sun"] !== element.hass.states["sun.sun"]
);
}
return true;
}
class WeatherCard extends LitElement {
static get properties() {
return {
_config: {},
hass: {},
};
}
static async getConfigElement() {
await import("./weather-card-editor.js");
return document.createElement("weather-card-editor");
}
static getStubConfig(hass, unusedEntities, allEntities) {
let entity = unusedEntities.find((eid) => eid.split(".")[0] === "weather");
if (!entity) {
entity = allEntities.find((eid) => eid.split(".")[0] === "weather");
}
return { entity };
}
setConfig(config) {
if (!config.entity) {
throw new Error("Please define a weather entity");
}
this._config = config;
}
shouldUpdate(changedProps) {
return hasConfigOrEntityChanged(this, changedProps);
}
render() {
if (!this._config || !this.hass) {
return html``;
}
this.numberElements = 0;
const stateObj = this.hass.states[this._config.entity];
if (!stateObj) {
return html`
<style>
.not-found {
flex: 1;
background-color: yellow;
padding: 8px;
}
</style>
<ha-card>
<div class="not-found">
Entity not available: ${this._config.entity}
</div>
</ha-card>
`;
}
return html`
<ha-card @click="${this._handleClick}">
${this._config.current !== false ? this.renderCurrent(stateObj) : ""}
${this._config.details !== false ? this.renderDetails(stateObj) : ""}
${this._config.forecast !== false
? this.renderForecast(stateObj.attributes.forecast)
: ""}
</ha-card>
`;
}
renderCurrent(stateObj) {
this.numberElements++;
return html`
<div class="current ${this.numberElements > 1 ? "spacer" : ""}">
<span
class="icon bigger"
style="background: none, url('${this.getWeatherIcon(
stateObj.state.toLowerCase(),
this.hass.states["sun.sun"]
)}') no-repeat; background-size: contain;"
>${stateObj.state}
</span>
${this._config.name
? html` <span class="title"> ${this._config.name} </span> `
: ""}
<span class="temp"
>${this.getUnit("temperature") == "°F"
? Math.round(stateObj.attributes.temperature)
: stateObj.attributes.temperature}</span
>
<span class="tempc"> ${this.getUnit("temperature")}</span>
</div>
`;
}
renderDetails(stateObj) {
const sun = this.hass.states["sun.sun"];
let next_rising;
let next_setting;
if (sun) {
next_rising = new Date(sun.attributes.next_rising);
next_setting = new Date(sun.attributes.next_setting);
}
this.numberElements++;
return html`
<ul class="variations ${this.numberElements > 1 ? "spacer" : ""}">
<li>
<ha-icon icon="mdi:water-percent"></ha-icon>
${stateObj.attributes.humidity}<span class="unit"> % </span>
</li>
<li>
<ha-icon icon="mdi:weather-windy"></ha-icon> ${windDirections[
parseInt((stateObj.attributes.wind_bearing + 11.25) / 22.5)
]}
${stateObj.attributes.wind_speed}<span class="unit">
${this.getUnit("length")}/h
</span>
</li>
<li>
<ha-icon icon="mdi:gauge"></ha-icon>
${stateObj.attributes.pressure}
<span class="unit">
${this.getUnit("air_pressure")}
</span>
</li>
<li>
<ha-icon icon="mdi:weather-fog"></ha-icon> ${stateObj.attributes
.visibility}<span class="unit">
${this.getUnit("length")}
</span>
</li>
${next_rising
? html`
<li>
<ha-icon icon="mdi:weather-sunset-up"></ha-icon>
${next_rising.toLocaleTimeString()}
</li>
`
: ""}
${next_setting
? html`
<li>
<ha-icon icon="mdi:weather-sunset-down"></ha-icon>
${next_setting.toLocaleTimeString()}
</li>
`
: ""}
</ul>
`;
}
renderForecast(forecast) {
if (!forecast || forecast.length === 0) {
return html``;
}
const lang = this.hass.selectedLanguage || this.hass.language;
this.numberElements++;
return html`
<div class="forecast clear ${this.numberElements > 1 ? "spacer" : ""}">
${forecast
.slice(
0,
this._config.number_of_forecasts
? this._config.number_of_forecasts
: 5
)
.map(
(daily) => html`
<div class="day">
<div class="dayname">
${this._config.hourly_forecast
? new Date(daily.datetime).toLocaleTimeString(lang, {
hour: "2-digit",
minute: "2-digit",
})
: new Date(daily.datetime).toLocaleDateString(lang, {
weekday: "short",
})}
</div>
<i
class="icon"
style="background: none, url('${this.getWeatherIcon(
daily.condition.toLowerCase()
)}') no-repeat; background-size: contain"
></i>
<div class="highTemp">
${daily.temperature}${this.getUnit("temperature")}
</div>
${daily.templow !== undefined
? html`
<div class="lowTemp">
${daily.templow}${this.getUnit("temperature")}
</div>
`
: ""}
${!this._config.hide_precipitation &&
daily.precipitation !== undefined &&
daily.precipitation !== null
? html`
<div class="precipitation">
${Math.round(daily.precipitation*10)/10} ${this.getUnit("precipitation")}
</div>
`
: ""}
${!this._config.hide_precipitation &&
daily.precipitation_probability !== undefined &&
daily.precipitation_probability !== null
? html`
<div class="precipitation_probability">
${Math.round(daily.precipitation_probability)} ${this.getUnit("precipitation_probability")}
</div>
`
: ""}
</div>
`
)}
</div>
`;
}
getWeatherIcon(condition, sun) {
return `${
this._config.icons
? this._config.icons
: "https://cdn.jsdelivr.net/gh/bramkragten/weather-card/dist/icons/"
}${
sun && sun.state == "below_horizon"
? weatherIconsNight[condition]
: weatherIconsDay[condition]
}.svg`;
}
getUnit(measure) {
const lengthUnit = this.hass.config.unit_system.length;
switch (measure) {
case "air_pressure":
return lengthUnit === "km" ? "hPa" : "inHg";
case "length":
return lengthUnit;
case "precipitation":
return lengthUnit === "km" ? "mm" : "in";
case "precipitation_probability":
return "%";
default:
return this.hass.config.unit_system[measure] || "";
}
}
_handleClick() {
fireEvent(this, "hass-more-info", { entityId: this._config.entity });
}
getCardSize() {
return 3;
}
static get styles() {
return css`
ha-card {
cursor: pointer;
margin: auto;
overflow: hidden;
padding-top: 1.3em;
padding-bottom: 1.3em;
padding-left: 1em;
padding-right: 1em;
position: relative;
}
.spacer {
padding-top: 1em;
}
.clear {
clear: both;
}
.title {
position: absolute;
left: 3em;
font-weight: 300;
font-size: 3em;
color: var(--primary-text-color);
}
.temp {
font-weight: 300;
font-size: 4em;
color: var(--primary-text-color);
position: absolute;
right: 1em;
}
.tempc {
font-weight: 300;
font-size: 1.5em;
vertical-align: super;
color: var(--primary-text-color);
position: absolute;
right: 1em;
margin-top: -14px;
margin-right: 7px;
}
@media (max-width: 460px) {
.title {
font-size: 2.2em;
left: 4em;
}
.temp {
font-size: 3em;
}
.tempc {
font-size: 1em;
}
}
.current {
padding: 1.2em 0;
margin-bottom: 3.5em;
}
.variations {
display: flex;
flex-flow: row wrap;
justify-content: space-between;
font-weight: 300;
color: var(--primary-text-color);
list-style: none;
padding: 0 1em;
margin: 0;
}
.variations ha-icon {
height: 22px;
margin-right: 5px;
color: var(--paper-item-icon-color);
}
.variations li {
flex-basis: auto;
width: 50%;
}
.variations li:nth-child(2n) {
text-align: right;
}
.variations li:nth-child(2n) ha-icon {
margin-right: 0;
margin-left: 8px;
float: right;
}
.unit {
font-size: 0.8em;
}
.forecast {
width: 100%;
margin: 0 auto;
display: flex;
}
.day {
flex: 1;
display: block;
text-align: center;
color: var(--primary-text-color);
border-right: 0.1em solid #d9d9d9;
line-height: 2;
box-sizing: border-box;
}
.dayname {
text-transform: uppercase;
}
.forecast .day:first-child {
margin-left: 0;
}
.forecast .day:nth-last-child(1) {
border-right: none;
margin-right: 0;
}
.highTemp {
font-weight: bold;
}
.lowTemp {
color: var(--secondary-text-color);
}
.precipitation {
color: var(--primary-text-color);
font-weight: 300;
}
.icon.bigger {
width: 10em;
height: 10em;
margin-top: -4em;
position: absolute;
left: 0em;
}
.icon {
width: 50px;
height: 50px;
margin-right: 5px;
display: inline-block;
vertical-align: middle;
background-size: contain;
background-position: center center;
background-repeat: no-repeat;
text-indent: -9999px;
}
.weather {
font-weight: 300;
font-size: 1.5em;
color: var(--primary-text-color);
text-align: left;
position: absolute;
top: -0.5em;
left: 6em;
word-wrap: break-word;
width: 30%;
}
`;
}
}
customElements.define("weather-card", WeatherCard);
File diff suppressed because one or more lines are too long
Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<config>
<header>
<header_item key="X-BBL-Client-Type" value="slicer"/>
<header_item key="X-BBL-Client-Version" value="02.05.00.66"/>
</header>
<plate>
<metadata key="index" value="1"/>
<metadata key="extruder_type" value="0"/>
<metadata key="nozzle_volume_type" value="0"/>
<metadata key="printer_model_id" value="BL-P001"/>
<metadata key="nozzle_diameters" value="0.4"/>
<metadata key="timelapse_type" value="0"/>
<metadata key="prediction" value="2777"/>
<metadata key="weight" value="11.04"/>
<metadata key="first_layer_time" value="227.031586"/>
<metadata key="outside" value="false"/>
<metadata key="support_used" value="false"/>
<metadata key="label_object_enabled" value="false"/>
<metadata key="filament_maps" value="1 1 1 1"/>
<metadata key="limit_filament_maps" value="0 0 0 0"/>
<object identify_id="365" name="Assembly" skipped="false" />
<filament id="3" tray_info_idx="GFG99" type="PETG" color="#161616" used_m="0.20" used_g="0.61" used_for_object="true" used_for_support="false" group_id="0" nozzle_diameter="0.40" volume_type="Standard"/>
<filament id="4" tray_info_idx="GFG00" type="PETG" color="#B28B33" used_m="3.47" used_g="10.43" used_for_object="true" used_for_support="false" group_id="0" nozzle_diameter="0.40" volume_type="Standard"/>
<warning msg="bed_temperature_too_high_than_filament" level="3" error_code ="1000C001" />
<layer_filament_lists>
<layer_filament_list filament_list="2" layer_ranges="15 17" />
<layer_filament_list filament_list="3" layer_ranges="0 14" />
</layer_filament_lists>
</plate>
</config>
+417
View File
@@ -0,0 +1,417 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>MeshCore Direct Links</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
<script src="https://unpkg.com/leaflet.heat@0.2.0/dist/leaflet-heat.js"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: #1a1a2e;
color: #fff;
}
#map {
width: 100%;
height: 100vh;
}
.stats {
position: absolute;
top: 10px;
left: 10px;
background: rgba(30, 30, 50, 0.95);
padding: 12px;
border-radius: 8px;
z-index: 1000;
font-size: 12px;
}
.stats h3 {
color: #a855f7;
margin-bottom: 8px;
font-size: 14px;
}
.stat-row {
margin: 4px 0;
color: #aaa;
}
.stat-value {
color: #fff;
font-weight: bold;
}
.legend {
position: absolute;
bottom: 20px;
left: 10px;
background: rgba(30, 30, 50, 0.95);
padding: 12px;
border-radius: 8px;
z-index: 1000;
font-size: 11px;
}
.legend-title {
margin-bottom: 8px;
font-weight: bold;
color: #a855f7;
}
.legend-item {
display: flex;
align-items: center;
gap: 6px;
margin: 4px 0;
}
.legend-dot {
width: 12px;
height: 12px;
border-radius: 50%;
}
.info-panel {
position: absolute;
top: 10px;
right: 10px;
background: rgba(30, 30, 50, 0.95);
padding: 15px;
border-radius: 8px;
z-index: 1000;
max-width: 250px;
max-height: 400px;
overflow-y: auto;
}
.info-panel h3 {
margin-bottom: 10px;
color: #a855f7;
font-size: 14px;
border-bottom: 1px solid #333;
padding-bottom: 8px;
cursor: pointer;
}
.node-item {
display: flex;
align-items: center;
gap: 8px;
padding: 4px 0;
border-bottom: 1px solid #2a2a4a;
font-size: 11px;
cursor: pointer;
}
.node-item:hover {
background: rgba(168, 85, 247, 0.2);
}
.node-item.active {
background: rgba(168, 85, 247, 0.3);
}
.node-item:last-child {
border-bottom: none;
}
.node-dot {
width: 12px;
height: 12px;
border-radius: 50%;
flex-shrink: 0;
}
.node-name {
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.node-count {
color: #a855f7;
font-weight: bold;
}
/* Dark map tiles */
.leaflet-tile-pane {
filter: invert(1) hue-rotate(180deg) brightness(0.8) contrast(1.2);
}
.leaflet-control-attribution {
background: rgba(30, 30, 50, 0.8) !important;
color: #666 !important;
}
.leaflet-control-attribution a {
color: #888 !important;
}
</style>
</head>
<body>
<div id="map"></div>
<div class="stats">
<h3>🔗 Direct Links Heatmap</h3>
<div class="stat-row">Time Window: <span class="stat-value" id="threshold-hours">--</span>h</div>
<div class="stat-row">Nodes: <span class="stat-value" id="node-count">0</span></div>
<div class="stat-row">Direct Links: <span class="stat-value" id="link-count">0</span></div>
<div class="stat-row">Max Links: <span class="stat-value" id="max-links">0</span></div>
</div>
<div class="legend">
<div class="legend-title">Link Density</div>
<div class="legend-item">
<div class="legend-dot" style="background: #0000ff;"></div>
<span>1-2 links</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #00ffff;"></div>
<span>3-5 links</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #00ff00;"></div>
<span>6-10 links</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #ffff00;"></div>
<span>11-20 links</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #ff0000;"></div>
<span>20+ links</span>
</div>
</div>
<div class="info-panel">
<h3 id="toggle-links">🔗 Top Connected Nodes <span id="links-status">(lines hidden)</span></h3>
<div id="node-list"></div>
</div>
<script>
// Initialize map
const map = L.map('map', {
center: [52.3, 0],
zoom: 9,
zoomControl: true
});
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap'
}).addTo(map);
let nodeData = [];
let linkData = [];
let heatLayer = null;
let markers = [];
let linkLines = [];
let lastDataHash = '';
let selectedNode = null;
let linksVisible = false;
function getDataHash(nodes, links, threshold) {
const nodeHash = JSON.stringify(nodes.map(d => d.name + d.link_count)).substring(0, 100);
const linkHash = links ? JSON.stringify(links.length) : '0';
return nodeHash + linkHash + (threshold || '');
}
function getColor(ratio) {
if (ratio < 0.2) return '#0000ff';
if (ratio < 0.4) return '#00ffff';
if (ratio < 0.6) return '#00ff00';
if (ratio < 0.8) return '#ffff00';
return '#ff0000';
}
function toggleLinks() {
linksVisible = !linksVisible;
linkLines.forEach(line => {
if (linksVisible) {
line.setStyle({ opacity: 0.5 });
} else {
line.setStyle({ opacity: 0 });
}
});
document.getElementById('links-status').textContent = linksVisible ? '(lines visible)' : '(lines hidden)';
}
document.getElementById('toggle-links').addEventListener('click', toggleLinks);
function highlightNodeLinks(nodeName) {
if (selectedNode === nodeName) {
selectedNode = null;
} else {
selectedNode = nodeName;
}
document.querySelectorAll('.node-item').forEach(item => {
if (item.dataset.nodeName === selectedNode) {
item.classList.add('active');
} else {
item.classList.remove('active');
}
});
linkLines.forEach(line => {
if (selectedNode === null) {
line.setStyle({ opacity: linksVisible ? 0.5 : 0 });
} else if (line.fromName === selectedNode || line.toName === selectedNode) {
line.setStyle({ opacity: 0.9, weight: 3 });
line.bringToFront();
} else {
line.setStyle({ opacity: 0.1 });
}
});
}
function updateMap(fitBounds = false) {
// Clear existing layers
if (heatLayer) map.removeLayer(heatLayer);
markers.forEach(m => map.removeLayer(m));
markers = [];
linkLines.forEach(l => map.removeLayer(l));
linkLines = [];
if (nodeData.length === 0) return;
const maxLinks = Math.max(...nodeData.map(d => d.link_count), 1);
const totalLinks = linkData.length;
// Update stats
document.getElementById('node-count').textContent = nodeData.length;
document.getElementById('link-count').textContent = totalLinks;
document.getElementById('max-links').textContent = maxLinks;
// Draw link lines (hidden by default)
linkData.forEach(link => {
const maxCount = Math.max(...linkData.map(l => l.count), 1);
const ratio = link.count / maxCount;
const color = getColor(ratio);
const polyline = L.polyline(
[[link.from_lat, link.from_lon], [link.to_lat, link.to_lon]],
{
color: color,
weight: 2,
opacity: 0,
dashArray: '5, 5'
}
).addTo(map);
polyline.fromName = link.from_name;
polyline.toName = link.to_name;
polyline.bindPopup(`
<div style="text-align: center;">
<strong>${link.from_name}</strong><br>
<br>
<strong>${link.to_name}</strong><br>
<span style="color: ${color}; font-size: 14px;">${link.count} times</span>
</div>
`);
linkLines.push(polyline);
});
// Create heatmap based on link count
const heatData = nodeData.map(node => [
node.lat,
node.lon,
node.link_count / maxLinks
]);
heatLayer = L.heatLayer(heatData, {
radius: 50,
blur: 35,
maxZoom: 10,
max: 1.0,
minOpacity: 0.3,
gradient: {
0.0: '#0000ff',
0.25: '#00ffff',
0.5: '#00ff00',
0.75: '#ffff00',
1.0: '#ff0000'
}
}).addTo(map);
// Add node markers
nodeData.forEach(node => {
const ratio = node.link_count / maxLinks;
const color = getColor(ratio);
const marker = L.circleMarker([node.lat, node.lon], {
radius: 4,
fillColor: color,
color: '#000',
weight: 1,
opacity: 1,
fillOpacity: 0.9
}).addTo(map);
marker.bindPopup(`
<div style="text-align: center;">
<strong>${node.name}</strong><br>
<span style="font-size: 11px; color: #888;">${node.node_type}</span><br>
<span style="color: ${color}; font-size: 18px; font-weight: bold;">
${node.link_count}
</span> direct links
</div>
`);
markers.push(marker);
});
// Update node list
const nodeList = document.getElementById('node-list');
const sortedNodes = [...nodeData].sort((a, b) => b.link_count - a.link_count);
nodeList.innerHTML = sortedNodes.map(node => {
const ratio = node.link_count / maxLinks;
const color = getColor(ratio);
return `
<div class="node-item" data-node-name="${node.name}" onclick="highlightNodeLinks('${node.name.replace(/'/g, "\\'")}')">
<div class="node-dot" style="background: ${color};"></div>
<span class="node-name" title="${node.name}">${node.name}</span>
<span class="node-count">${node.link_count}</span>
</div>
`;
}).join('');
if (fitBounds && nodeData.length > 1) {
const bounds = L.latLngBounds(nodeData.map(d => [d.lat, d.lon]));
map.fitBounds(bounds, { padding: [50, 50] });
}
}
// Load initial data
fetch('/local/meshcore_directlinks_data.json')
.then(response => response.json())
.then(data => {
if (data.nodes && Array.isArray(data.nodes)) {
nodeData = data.nodes;
linkData = data.links || [];
if (data.threshold_hours) {
document.getElementById('threshold-hours').textContent = data.threshold_hours;
}
lastDataHash = getDataHash(nodeData, linkData, data.threshold_hours);
updateMap(true);
}
})
.catch(err => console.log('No data file found:', err));
// Auto-refresh
setInterval(() => {
fetch('/local/meshcore_directlinks_data.json?t=' + Date.now())
.then(response => response.json())
.then(data => {
if (data.nodes && Array.isArray(data.nodes)) {
const newHash = getDataHash(data.nodes, data.links, data.threshold_hours);
if (data.threshold_hours) {
document.getElementById('threshold-hours').textContent = data.threshold_hours;
}
if (newHash !== lastDataHash) {
nodeData = data.nodes;
linkData = data.links || [];
lastDataHash = newHash;
updateMap(false);
}
}
})
.catch(err => console.log('Refresh failed:', err));
}, 10000);
</script>
</body>
</html>
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
+452
View File
@@ -0,0 +1,452 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>MeshCore Direct Links</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
<script src="https://unpkg.com/leaflet.heat@0.2.0/dist/leaflet-heat.js"></script>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: #1a1a2e;
color: #fff;
}
#map { width: 100%; height: 100vh; }
.stats {
position: absolute;
top: 10px;
left: 10px;
background: rgba(30, 30, 50, 0.95);
padding: 12px;
border-radius: 8px;
z-index: 1000;
font-size: 12px;
}
.stats h3 { color: #a855f7; margin-bottom: 8px; font-size: 14px; }
.stat-row { margin: 4px 0; color: #aaa; }
.stat-value { color: #fff; font-weight: bold; }
.legend {
position: absolute;
bottom: 80px;
left: 10px;
background: rgba(30, 30, 50, 0.95);
padding: 12px;
border-radius: 8px;
z-index: 1000;
font-size: 11px;
}
.legend-title { margin-bottom: 8px; font-weight: bold; color: #a855f7; }
.legend-item { display: flex; align-items: center; gap: 6px; margin: 4px 0; }
.legend-dot { width: 12px; height: 12px; border-radius: 50%; }
.info-panel {
position: absolute;
top: 10px;
right: 10px;
background: rgba(30, 30, 50, 0.95);
padding: 15px;
border-radius: 8px;
z-index: 1000;
max-width: 250px;
max-height: 400px;
overflow-y: auto;
}
.info-panel h3 {
margin-bottom: 10px;
color: #a855f7;
font-size: 14px;
border-bottom: 1px solid #333;
padding-bottom: 8px;
}
.node-item {
display: flex;
align-items: center;
gap: 8px;
padding: 4px 0;
border-bottom: 1px solid #2a2a4a;
font-size: 11px;
cursor: pointer;
transition: background 0.2s;
}
.node-item:hover { background: rgba(168, 85, 247, 0.2); }
.node-item.active { background: rgba(168, 85, 247, 0.3); }
.node-dot { width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0; }
.node-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.node-count { color: #888; font-weight: bold; }
#node-search {
width: 100%;
padding: 6px;
margin-bottom: 10px;
background: #2a2a4a;
border: 1px solid #444;
border-radius: 4px;
color: #fff;
font-size: 12px;
}
.playback-panel {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
background: rgba(30, 30, 50, 0.95);
padding: 12px 20px;
border-radius: 8px;
z-index: 1000;
display: flex;
align-items: center;
gap: 15px;
box-shadow: 0 4px 15px rgba(0,0,0,0.3);
}
.playback-btn {
background: #a855f7;
border: none;
color: #fff;
padding: 8px 12px;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
transition: background 0.2s;
}
.playback-btn:hover { background: #9333ea; }
.playback-btn:disabled { background: #444; cursor: not-allowed; }
.playback-btn.live { background: #ef4444; }
.playback-slider { width: 200px; cursor: pointer; }
.playback-time { color: #fff; font-size: 12px; min-width: 110px; text-align: center; }
.playback-time.live { color: #ef4444; font-weight: bold; }
.playback-info { color: #888; font-size: 11px; }
.snapshot-count { color: #a855f7; font-weight: bold; }
.threshold-control {
display: flex;
align-items: center;
gap: 6px;
border-left: 1px solid #444;
padding-left: 12px;
margin-left: 5px;
}
.threshold-control label { font-size: 10px; color: #888; }
.threshold-slider { width: 70px; cursor: pointer; }
.threshold-value { font-size: 11px; color: #a855f7; min-width: 32px; }
.leaflet-tile-pane { filter: invert(1) hue-rotate(180deg) brightness(0.8) contrast(1.2); }
.leaflet-control-attribution { background: rgba(30, 30, 50, 0.8) !important; color: #666 !important; }
.leaflet-control-attribution a { color: #888 !important; }
</style>
</head>
<body>
<div id="map"></div>
<div class="stats">
<h3>🔗 Direct Links Heatmap</h3>
<div class="stat-row">Time Window: <span class="stat-value" id="threshold-hours">--</span>h</div>
<div class="stat-row">Nodes: <span class="stat-value" id="node-count">0</span></div>
<div class="stat-row">Direct Links: <span class="stat-value" id="link-count">0</span></div>
<div class="stat-row">Max Links: <span class="stat-value" id="max-links">0</span></div>
</div>
<div class="legend">
<div class="legend-title">Link Density</div>
<div class="legend-item"><div class="legend-dot" style="background: #0000ff;"></div><span>1-2 links</span></div>
<div class="legend-item"><div class="legend-dot" style="background: #00ffff;"></div><span>3-5 links</span></div>
<div class="legend-item"><div class="legend-dot" style="background: #00ff00;"></div><span>6-10 links</span></div>
<div class="legend-item"><div class="legend-dot" style="background: #ffff00;"></div><span>11-20 links</span></div>
<div class="legend-item"><div class="legend-dot" style="background: #ff0000;"></div><span>20+ links</span></div>
</div>
<div class="info-panel">
<h3>🔗 Top Connected Nodes</h3>
<input type="text" id="node-search" placeholder="Search nodes..." oninput="filterNodes()">
<div id="node-list"></div>
</div>
<div class="playback-panel">
<button class="playback-btn" id="btn-play" title="Play history">▶️</button>
<button class="playback-btn live" id="btn-live" title="Go live">🔴 LIVE</button>
<input type="range" class="playback-slider" id="timeline" min="0" max="0" value="0">
<div class="playback-time live" id="playback-time">● LIVE</div>
<div class="playback-info"><span class="snapshot-count" id="snapshot-count">0</span> snaps</div>
<div class="threshold-control">
<label>Filter:</label>
<input type="range" class="threshold-slider" id="playback-threshold" min="1" max="48" value="48">
<span class="threshold-value" id="playback-threshold-value">ALL</span>
</div>
</div>
<script>
const map = L.map('map', { center: [52.3, 0], zoom: 9, zoomControl: true, zoomSnap: 0.25, zoomDelta: 0.5, wheelPxPerZoomLevel: 120 });
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: '© OpenStreetMap' }).addTo(map);
let nodeData = [], linkData = [], heatLayer = null, markers = [], linkLines = [];
let selectedNode = null;
let allSnapshotLinks = []; // Store all links for highlighting regardless of threshold
// Playback state - loaded from server
let snapshots = [], isPlaying = false, playbackIndex = 0, playbackInterval = null, liveMode = true;
const PLAYBACK_SPEED = 400;
function loadSnapshots() {
fetch('/local/meshcore_directlinks_history.json?t=' + Date.now())
.then(r => r.json())
.then(data => {
if (data.snapshots && Array.isArray(data.snapshots)) {
snapshots = data.snapshots;
updateSnapshotCount();
}
})
.catch(e => {});
}
function updateSnapshotCount() {
document.getElementById('snapshot-count').textContent = snapshots.length;
document.getElementById('timeline').max = Math.max(0, snapshots.length - 1);
if (liveMode && snapshots.length > 0) {
document.getElementById('timeline').value = snapshots.length - 1;
}
}
function formatTime(ts) {
const d = new Date(ts * 1000);
return d.toLocaleString('en-GB', { day: '2-digit', month: '2-digit', hour: '2-digit', minute: '2-digit' });
}
document.getElementById('btn-play').addEventListener('click', function() {
if (snapshots.length === 0) return;
if (isPlaying) {
isPlaying = false;
clearInterval(playbackInterval);
this.textContent = '▶️';
} else {
isPlaying = true;
liveMode = false;
this.textContent = '⏸️';
document.getElementById('btn-live').classList.remove('live');
document.getElementById('playback-time').classList.remove('live');
if (playbackIndex >= snapshots.length - 1) playbackIndex = 0;
playbackInterval = setInterval(() => {
playbackIndex++;
if (playbackIndex >= snapshots.length) {
isPlaying = false;
clearInterval(playbackInterval);
document.getElementById('btn-play').textContent = '▶️';
playbackIndex = snapshots.length - 1;
}
document.getElementById('timeline').value = playbackIndex;
displaySnapshot(playbackIndex);
}, PLAYBACK_SPEED);
}
});
document.getElementById('btn-live').addEventListener('click', goLive);
function goLive() {
isPlaying = false;
liveMode = true;
allSnapshotLinks = []; // Clear snapshot links when going live
clearInterval(playbackInterval);
document.getElementById('btn-play').textContent = '▶️';
document.getElementById('btn-live').classList.add('live');
document.getElementById('playback-time').textContent = '● LIVE';
document.getElementById('playback-time').classList.add('live');
if (snapshots.length > 0) document.getElementById('timeline').value = snapshots.length - 1;
fetchLiveData();
}
document.getElementById('timeline').addEventListener('input', function() {
if (snapshots.length === 0) return;
liveMode = false;
isPlaying = false;
clearInterval(playbackInterval);
document.getElementById('btn-play').textContent = '▶️';
document.getElementById('btn-live').classList.remove('live');
document.getElementById('playback-time').classList.remove('live');
playbackIndex = parseInt(this.value);
displaySnapshot(playbackIndex);
});
// Get threshold from Home Assistant (read from live data file)
let currentThresholdHours = 4; // Default for live mode
let playbackThresholdHours = 48; // Default for playback (48 = show all)
function loadThreshold() {
fetch('/local/meshcore_directlinks_data.json?t=' + Date.now())
.then(r => r.json())
.then(data => {
if (data.threshold_hours) {
currentThresholdHours = data.threshold_hours;
if (liveMode) {
document.getElementById('threshold-hours').textContent = currentThresholdHours;
}
}
}).catch(e => {});
}
// Playback threshold slider
document.getElementById('playback-threshold').addEventListener('input', function() {
playbackThresholdHours = parseInt(this.value);
const display = playbackThresholdHours >= 48 ? 'ALL' : playbackThresholdHours + 'h';
document.getElementById('playback-threshold-value').textContent = display;
if (!liveMode && snapshots.length > 0) {
displaySnapshot(playbackIndex);
}
});
function filterNodesByThreshold(nodes, links, snapshotTimestamp) {
if (!nodes || nodes.length === 0) return { nodes: [], links: [] };
// If threshold is 48+ (ALL), return all data
if (playbackThresholdHours >= 48) {
return { nodes: nodes, links: links || [] };
}
// If nodes don't have last_seen timestamps, return all (old format data)
const hasTimestamps = nodes.some(n => n.last_seen !== undefined && n.last_seen > 0);
if (!hasTimestamps) {
return { nodes: nodes, links: links || [] };
}
const thresholdSeconds = playbackThresholdHours * 3600;
const cutoff = snapshotTimestamp - thresholdSeconds;
const filteredNodes = nodes.filter(n => (n.last_seen || 0) >= cutoff);
const filteredNodeNames = new Set(filteredNodes.map(n => n.name));
// Filter links to only include those between active nodes
const filteredLinks = (links || []).filter(l =>
(l.last_seen || 0) >= cutoff &&
filteredNodeNames.has(l.from_name) &&
filteredNodeNames.has(l.to_name)
);
return { nodes: filteredNodes, links: filteredLinks };
}
function displaySnapshot(index) {
if (index < 0 || index >= snapshots.length) return;
const snapshot = snapshots[index];
const snapshotTime = snapshot.timestamp;
// Store ALL links from snapshot for highlighting
allSnapshotLinks = snapshot.links || [];
// Filter nodes by playback threshold setting
const filtered = filterNodesByThreshold(snapshot.nodes || [], snapshot.links || [], snapshotTime);
nodeData = filtered.nodes;
linkData = filtered.links;
document.getElementById('playback-time').textContent = formatTime(snapshotTime);
const thresholdDisplay = playbackThresholdHours >= 48 ? 'ALL' : playbackThresholdHours;
document.getElementById('threshold-hours').textContent = thresholdDisplay;
updateMap(false);
}
function getColor(ratio) {
if (ratio < 0.2) return '#0000ff';
if (ratio < 0.4) return '#00ffff';
if (ratio < 0.6) return '#00ff00';
if (ratio < 0.8) return '#ffff00';
return '#ff0000';
}
function filterNodes() {
const searchTerm = document.getElementById('node-search').value.toLowerCase();
document.querySelectorAll('.node-item').forEach(item => {
item.style.display = item.dataset.nodeName.toLowerCase().includes(searchTerm) ? 'flex' : 'none';
});
}
function highlightNodeLinks(nodeName) {
selectedNode = selectedNode === nodeName ? null : nodeName;
document.querySelectorAll('.node-item').forEach(item => {
item.classList.toggle('active', item.dataset.nodeName === selectedNode);
});
linkLines.forEach(line => {
if (selectedNode === null) line.setStyle({ opacity: 0 });
else if (line.fromName === selectedNode || line.toName === selectedNode) { line.setStyle({ opacity: 0.8, weight: 3 }); line.bringToFront(); }
else line.setStyle({ opacity: 0 });
});
}
function updateMap(fitBounds = false) {
if (heatLayer) map.removeLayer(heatLayer);
markers.forEach(m => map.removeLayer(m));
markers = [];
linkLines.forEach(l => map.removeLayer(l));
linkLines = [];
if (nodeData.length === 0) return;
const maxLinks = Math.max(...nodeData.map(d => d.link_count), 1);
document.getElementById('node-count').textContent = nodeData.length;
document.getElementById('link-count').textContent = linkData.length;
document.getElementById('max-links').textContent = maxLinks;
const heatData = nodeData.map(node => [node.lat, node.lon, node.link_count / maxLinks]);
heatLayer = L.heatLayer(heatData, { radius: 45, blur: 30, maxZoom: 10, max: 1.0, minOpacity: 0.3,
gradient: { 0.0: '#0000ff', 0.25: '#00ffff', 0.5: '#00ff00', 0.75: '#ffff00', 1.0: '#ff0000' }
}).addTo(map);
// Draw ALL links from snapshot (not just filtered) so highlighting works
const linksToUse = allSnapshotLinks.length > 0 ? allSnapshotLinks : linkData;
if (linksToUse && linksToUse.length > 0) {
linksToUse.forEach(link => {
const polyline = L.polyline([[link.from_lat, link.from_lon], [link.to_lat, link.to_lon]], { color: '#a855f7', weight: 3, opacity: 0, dashArray: '5, 10' }).addTo(map);
polyline.fromName = link.from_name;
polyline.toName = link.to_name;
polyline.bindPopup(`${link.from_name} ↔ ${link.to_name}<br>Count: ${link.count}`);
linkLines.push(polyline);
});
}
nodeData.forEach(node => {
const ratio = node.link_count / maxLinks;
const marker = L.circleMarker([node.lat, node.lon], { radius: 4, fillColor: getColor(ratio), color: '#000', weight: 1, opacity: 1, fillOpacity: 0.9 }).addTo(map);
marker.bindPopup(`<div style="text-align:center;"><strong>${node.name}</strong><br><span style="color:${getColor(ratio)};font-size:18px;font-weight:bold;">${node.link_count}</span> direct links</div>`);
markers.push(marker);
});
const nodeList = document.getElementById('node-list');
const sortedNodes = [...nodeData].sort((a, b) => b.link_count - a.link_count);
nodeList.innerHTML = sortedNodes.map(node => {
const color = getColor(node.link_count / maxLinks);
return `<div class="node-item" data-node-name="${node.name}" onclick="highlightNodeLinks('${node.name.replace(/'/g, "\\'")}')"><div class="node-dot" style="background:${color};"></div><span class="node-name" title="${node.name}">${node.name}</span><span class="node-count">${node.link_count}</span></div>`;
}).join('');
if (fitBounds && nodeData.length > 1) map.fitBounds(L.latLngBounds(nodeData.map(d => [d.lat, d.lon])), { padding: [50, 50] });
}
function fetchLiveData() {
fetch('/local/meshcore_directlinks_data.json?t=' + Date.now())
.then(r => r.json())
.then(data => {
if (data.nodes && Array.isArray(data.nodes)) {
if (data.threshold_hours) document.getElementById('threshold-hours').textContent = data.threshold_hours;
if (liveMode) {
nodeData = data.nodes;
linkData = data.links || [];
updateMap(markers.length === 0);
}
}
}).catch(e => {});
}
// Load snapshots from server
loadSnapshots();
loadThreshold();
setInterval(loadSnapshots, 30000); // Check every 30 seconds
setInterval(loadThreshold, 60000); // Update threshold every minute
// Initial live data
fetch('/local/meshcore_directlinks_data.json')
.then(r => r.json())
.then(data => {
if (data.nodes && Array.isArray(data.nodes)) {
nodeData = data.nodes;
linkData = data.links || [];
if (data.threshold_hours) document.getElementById('threshold-hours').textContent = data.threshold_hours;
updateMap(true);
}
}).catch(e => {});
setInterval(fetchLiveData, 10000);
</script>
</body>
</html>
+470
View File
@@ -0,0 +1,470 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>MeshCore Hop Frequency Heatmap</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
<script src="https://unpkg.com/leaflet.heat@0.2.0/dist/leaflet-heat.js"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: #1a1a2e;
color: #fff;
}
#map {
width: 100%;
height: 100vh;
}
.info-panel {
position: absolute;
top: 10px;
right: 10px;
background: rgba(30, 30, 50, 0.95);
padding: 15px;
border-radius: 8px;
z-index: 1000;
max-width: 280px;
max-height: 400px;
overflow-y: auto;
box-shadow: 0 4px 15px rgba(0,0,0,0.3);
}
.info-panel h3 {
margin-bottom: 10px;
color: #60a5fa;
font-size: 14px;
border-bottom: 1px solid #333;
padding-bottom: 8px;
}
.node-item {
display: flex;
align-items: center;
gap: 8px;
padding: 6px 0;
border-bottom: 1px solid #2a2a4a;
font-size: 12px;
cursor: pointer;
transition: background 0.2s;
}
.node-item:hover {
background: rgba(96, 165, 250, 0.2);
}
.node-item.active {
background: rgba(96, 165, 250, 0.3);
}
.node-item:last-child {
border-bottom: none;
}
.node-dot {
width: 12px;
height: 12px;
border-radius: 50%;
flex-shrink: 0;
}
.node-name {
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.node-count {
color: #888;
font-weight: bold;
}
.legend {
position: absolute;
bottom: 20px;
left: 10px;
background: rgba(30, 30, 50, 0.95);
padding: 12px;
border-radius: 8px;
z-index: 1000;
font-size: 11px;
}
.legend-title {
margin-bottom: 8px;
font-weight: bold;
color: #60a5fa;
}
.legend-item {
display: flex;
align-items: center;
gap: 6px;
margin: 4px 0;
}
.legend-dot {
width: 14px;
height: 14px;
border-radius: 50%;
}
.stats {
position: absolute;
top: 10px;
left: 10px;
background: rgba(30, 30, 50, 0.95);
padding: 12px;
border-radius: 8px;
z-index: 1000;
font-size: 12px;
}
.stats h3 {
color: #60a5fa;
margin-bottom: 8px;
font-size: 14px;
}
.stat-row {
margin: 4px 0;
color: #aaa;
}
.stat-value {
color: #fff;
font-weight: bold;
}
/* Dark map tiles */
.leaflet-tile-pane {
filter: invert(1) hue-rotate(180deg) brightness(0.8) contrast(1.2);
}
.leaflet-control-attribution {
background: rgba(30, 30, 50, 0.8) !important;
color: #666 !important;
}
.leaflet-control-attribution a {
color: #888 !important;
}
.node-icon {
background: transparent;
border: none;
}
.node-icon svg {
filter: drop-shadow(1px 1px 2px rgba(0,0,0,0.5));
}
</style>
</head>
<body>
<div id="map"></div>
<div class="stats">
<h3>📡 Hop Frequency Heatmap</h3>
<div class="stat-row">Time Window: <span class="stat-value" id="threshold-hours">--</span>h</div>
<div class="stat-row">Nodes: <span class="stat-value" id="node-count">0</span></div>
<div class="stat-row">Paths: <span class="stat-value" id="path-count">0</span></div>
<div class="stat-row">Total Traffic: <span class="stat-value" id="total-traffic">0</span></div>
<div class="stat-row">Max Uses: <span class="stat-value" id="max-uses">0</span></div>
</div>
<div class="info-panel">
<h3 id="toggle-icons" style="cursor: pointer;">🔥 Top Hop Nodes <span id="icons-status">(visible)</span></h3>
<div id="node-list"></div>
</div>
<div class="legend">
<div class="legend-title">Traffic Intensity</div>
<div class="legend-item">
<div class="legend-dot" style="background: #0000ff;"></div>
<span>Low</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #00ffff;"></div>
<span>Light</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #00ff00;"></div>
<span>Medium</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #ffff00;"></div>
<span>High</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #ff0000;"></div>
<span>Very High</span>
</div>
</div>
<script>
// Initialize map centered on UK
const map = L.map('map', {
center: [52.3, 0],
zoom: 9,
zoomControl: true
});
// Dark map tiles
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap'
}).addTo(map);
// Hop data - loaded from AppDaemon-generated JSON file
let hopData = [];
// Try to load data from external JSON file (generated by AppDaemon)
fetch('/local/meshcore_heatmap_data.json')
.then(response => response.json())
.then(data => {
// Handle new format with metadata
if (data.nodes && Array.isArray(data.nodes)) {
hopData = data.nodes;
pathData = data.paths || [];
if (data.threshold_hours) {
document.getElementById('threshold-hours').textContent = data.threshold_hours;
}
lastDataHash = getDataHash(hopData, pathData, data.threshold_hours);
} else if (Array.isArray(data) && data.length > 0) {
// Old format - just array of nodes
hopData = data;
pathData = [];
lastDataHash = getDataHash(hopData, pathData, null);
}
updateMap(true); // Fit bounds on initial load
})
.catch(err => {
console.log('Using sample data - no external data file found');
updateMap(true);
});
let heatLayer = null;
let markers = [];
let pathLines = [];
let lastDataHash = '';
let initialLoadDone = false;
let pathData = [];
function getColor(ratio) {
if (ratio < 0.2) return '#0000ff'; // Blue
if (ratio < 0.4) return '#00ffff'; // Cyan
if (ratio < 0.6) return '#00ff00'; // Green
if (ratio < 0.8) return '#ffff00'; // Yellow
return '#ff0000'; // Red
}
let selectedNode = null;
let iconsVisible = true;
function toggleIcons() {
iconsVisible = !iconsVisible;
markers.forEach(marker => {
marker.setStyle({
opacity: iconsVisible ? 1 : 0,
fillOpacity: iconsVisible ? 0.9 : 0
});
});
document.getElementById('icons-status').textContent = iconsVisible ? '(visible)' : '(hidden)';
}
// Add click handler for toggle
document.getElementById('toggle-icons').addEventListener('click', toggleIcons);
function highlightNodePaths(nodeName) {
// Toggle selection
if (selectedNode === nodeName) {
selectedNode = null;
} else {
selectedNode = nodeName;
}
// Update node list active state
document.querySelectorAll('.node-item').forEach(item => {
if (item.dataset.nodeName === selectedNode) {
item.classList.add('active');
} else {
item.classList.remove('active');
}
});
// Update path line styles
pathLines.forEach(line => {
if (selectedNode === null) {
// Hide all lines
line.setStyle({ opacity: 0 });
} else if (line.pathNodes && line.pathNodes.includes(selectedNode)) {
// Show paths through this node - dotted lines
line.setStyle({
dashArray: '8, 8',
weight: 3,
opacity: 0.8
});
line.bringToFront();
} else {
// Hide other paths
line.setStyle({ opacity: 0 });
}
});
}
function getDataHash(nodes, paths, threshold) {
// Simple hash to detect data changes - include threshold
const nodeHash = JSON.stringify(nodes.map(d => d.name + d.use_count)).substring(0, 100);
const pathHash = paths ? JSON.stringify(paths.length) : '0';
const thresholdHash = threshold ? threshold.toString() : '0';
return nodeHash + pathHash + thresholdHash;
}
function updateMap(fitBounds = false) {
// Clear existing layers
if (heatLayer) map.removeLayer(heatLayer);
markers.forEach(m => map.removeLayer(m));
markers = [];
pathLines.forEach(p => map.removeLayer(p));
pathLines = [];
if (hopData.length === 0) return;
const maxCount = Math.max(...hopData.map(d => d.use_count));
const totalTraffic = hopData.reduce((sum, d) => sum + d.use_count, 0);
// Update stats
document.getElementById('node-count').textContent = hopData.length;
document.getElementById('path-count').textContent = pathData.length;
document.getElementById('total-traffic').textContent = totalTraffic;
document.getElementById('max-uses').textContent = maxCount;
// Draw path lines but hide them by default
// Color based on hop count (fewer hops = hotter/more direct)
const maxHops = Math.max(...pathData.map(p => p.hops), 1);
pathData.forEach((path, idx) => {
if (path.coords && path.coords.length >= 2) {
const latlngs = path.coords.map(c => [c.lat, c.lon]);
// Invert ratio - fewer hops = higher intensity (red), more hops = lower (blue)
const ratio = 1 - ((path.hops - 2) / Math.max(maxHops - 2, 1));
const color = getColor(ratio);
const polyline = L.polyline(latlngs, {
color: color,
weight: 3,
opacity: 0, // Hidden by default
dashArray: '8, 8'
}).addTo(map);
// Store node names this path goes through for highlighting
polyline.pathNodes = path.coords.map(c => c.name);
polyline.sender = path.sender;
polyline.pathColor = color;
polyline.bindPopup(`
<div style="text-align: center;">
<strong>${path.sender}</strong><br>
<span style="color: ${color}; font-size: 18px; font-weight: bold;">
${path.hops}
</span> hops
</div>
`);
pathLines.push(polyline);
}
});
// Create heatmap data
// Format: [lat, lon, intensity]
const heatData = hopData.map(node => [
node.lat,
node.lon,
node.use_count / maxCount // Normalized intensity
]);
// Add heatmap layer - smooth gradient style
heatLayer = L.heatLayer(heatData, {
radius: 50,
blur: 35,
maxZoom: 10,
max: 1.0,
minOpacity: 0.3,
gradient: {
0.0: '#0000ff', // Blue
0.25: '#00ffff', // Cyan
0.5: '#00ff00', // Green
0.75: '#ffff00', // Yellow
1.0: '#ff0000' // Red
}
}).addTo(map);
// Add simple circle markers
hopData.forEach(node => {
const ratio = node.use_count / maxCount;
const color = getColor(ratio);
const marker = L.circleMarker([node.lat, node.lon], {
radius: 4,
fillColor: color,
color: '#000',
weight: 1,
opacity: iconsVisible ? 1 : 0,
fillOpacity: iconsVisible ? 0.9 : 0
}).addTo(map);
marker.bindPopup(`
<div style="text-align: center;">
<strong>${node.name}</strong><br>
<span style="color: ${color}; font-size: 18px; font-weight: bold;">
${node.use_count}
</span> uses
</div>
`);
markers.push(marker);
});
// Update node list with clickable items
const nodeList = document.getElementById('node-list');
const sortedNodes = [...hopData].sort((a, b) => b.use_count - a.use_count);
nodeList.innerHTML = sortedNodes.slice(0, 15).map((node, idx) => {
const ratio = node.use_count / maxCount;
const color = getColor(ratio);
return `
<div class="node-item" data-node-name="${node.name}" onclick="highlightNodePaths('${node.name.replace(/'/g, "\\'")}')">
<div class="node-dot" style="background: ${color};"></div>
<span class="node-name" title="${node.name}">${node.name}</span>
<span class="node-count">${node.use_count}</span>
</div>
`;
}).join('');
// Only fit bounds on initial load
if (fitBounds && hopData.length > 1) {
const bounds = L.latLngBounds(hopData.map(d => [d.lat, d.lon]));
map.fitBounds(bounds, { padding: [50, 50] });
}
}
// Auto-refresh every 10 seconds - only update if data changed
setInterval(() => {
fetch('/local/meshcore_heatmap_data.json?t=' + Date.now())
.then(response => response.json())
.then(data => {
let newData = [];
let newPaths = [];
let newThreshold = null;
if (data.nodes && Array.isArray(data.nodes)) {
newData = data.nodes;
newPaths = data.paths || [];
newThreshold = data.threshold_hours;
} else if (Array.isArray(data) && data.length > 0) {
newData = data;
}
// Always update threshold display
if (newThreshold) {
document.getElementById('threshold-hours').textContent = newThreshold;
}
// Only redraw map if data actually changed (including threshold)
const newHash = getDataHash(newData, newPaths, newThreshold);
if (newHash !== lastDataHash) {
hopData = newData;
pathData = newPaths;
lastDataHash = newHash;
updateMap(false); // Don't fit bounds on refresh
}
})
.catch(err => console.log('Refresh failed:', err));
}, 10000);
</script>
</body>
</html>
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+438
View File
@@ -0,0 +1,438 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>MeshCore Hop Frequency Heatmap</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
<script src="https://unpkg.com/leaflet.heat@0.2.0/dist/leaflet-heat.js"></script>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: #1a1a2e;
color: #fff;
}
#map { width: 100%; height: 100vh; }
.info-panel {
position: absolute;
top: 10px;
right: 10px;
background: rgba(30, 30, 50, 0.95);
padding: 15px;
border-radius: 8px;
z-index: 1000;
max-width: 280px;
max-height: 400px;
overflow-y: auto;
box-shadow: 0 4px 15px rgba(0,0,0,0.3);
}
.info-panel h3 {
margin-bottom: 10px;
color: #60a5fa;
font-size: 14px;
border-bottom: 1px solid #333;
padding-bottom: 8px;
cursor: pointer;
}
.node-item {
display: flex;
align-items: center;
gap: 8px;
padding: 6px 0;
border-bottom: 1px solid #2a2a4a;
font-size: 12px;
cursor: pointer;
transition: background 0.2s;
}
.node-item:hover { background: rgba(96, 165, 250, 0.2); }
.node-item.active { background: rgba(96, 165, 250, 0.3); }
.node-item:last-child { border-bottom: none; }
.node-dot { width: 12px; height: 12px; border-radius: 50%; flex-shrink: 0; }
.node-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.node-count { color: #888; font-weight: bold; }
.legend {
position: absolute;
bottom: 80px;
left: 10px;
background: rgba(30, 30, 50, 0.95);
padding: 12px;
border-radius: 8px;
z-index: 1000;
font-size: 11px;
}
.legend-title { margin-bottom: 8px; font-weight: bold; color: #60a5fa; }
.legend-item { display: flex; align-items: center; gap: 6px; margin: 4px 0; }
.legend-dot { width: 14px; height: 14px; border-radius: 50%; }
.stats {
position: absolute;
top: 10px;
left: 10px;
background: rgba(30, 30, 50, 0.95);
padding: 12px;
border-radius: 8px;
z-index: 1000;
font-size: 12px;
}
.stats h3 { color: #60a5fa; margin-bottom: 8px; font-size: 14px; }
.stat-row { margin: 4px 0; color: #aaa; }
.stat-value { color: #fff; font-weight: bold; }
.playback-panel {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
background: rgba(30, 30, 50, 0.95);
padding: 12px 20px;
border-radius: 8px;
z-index: 1000;
display: flex;
align-items: center;
gap: 15px;
box-shadow: 0 4px 15px rgba(0,0,0,0.3);
}
.playback-btn {
background: #60a5fa;
border: none;
color: #fff;
padding: 8px 12px;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
transition: background 0.2s;
}
.playback-btn:hover { background: #3b82f6; }
.playback-btn:disabled { background: #444; cursor: not-allowed; }
.playback-btn.live { background: #ef4444; }
.playback-slider { width: 200px; cursor: pointer; }
.playback-time { color: #fff; font-size: 12px; min-width: 110px; text-align: center; }
.playback-time.live { color: #ef4444; font-weight: bold; }
.playback-info { color: #888; font-size: 11px; }
.snapshot-count { color: #60a5fa; font-weight: bold; }
.threshold-control {
display: flex;
align-items: center;
gap: 6px;
border-left: 1px solid #444;
padding-left: 12px;
margin-left: 5px;
}
.threshold-control label { font-size: 10px; color: #888; }
.threshold-slider { width: 70px; cursor: pointer; }
.threshold-value { font-size: 11px; color: #60a5fa; min-width: 32px; }
.leaflet-tile-pane { filter: invert(1) hue-rotate(180deg) brightness(0.8) contrast(1.2); }
.leaflet-control-attribution { background: rgba(30, 30, 50, 0.8) !important; color: #666 !important; }
.leaflet-control-attribution a { color: #888 !important; }
</style>
</head>
<body>
<div id="map"></div>
<div class="stats">
<h3>📡 Hop Frequency Heatmap</h3>
<div class="stat-row">Time Window: <span class="stat-value" id="threshold-hours">--</span>h</div>
<div class="stat-row">Nodes: <span class="stat-value" id="node-count">0</span></div>
<div class="stat-row">Paths: <span class="stat-value" id="path-count">0</span></div>
<div class="stat-row">Total Traffic: <span class="stat-value" id="total-traffic">0</span></div>
<div class="stat-row">Max Uses: <span class="stat-value" id="max-uses">0</span></div>
</div>
<div class="legend">
<div class="legend-title">Traffic Intensity</div>
<div class="legend-item"><div class="legend-dot" style="background: #0000ff;"></div><span>Low</span></div>
<div class="legend-item"><div class="legend-dot" style="background: #00ffff;"></div><span>Light</span></div>
<div class="legend-item"><div class="legend-dot" style="background: #00ff00;"></div><span>Medium</span></div>
<div class="legend-item"><div class="legend-dot" style="background: #ffff00;"></div><span>High</span></div>
<div class="legend-item"><div class="legend-dot" style="background: #ff0000;"></div><span>Very High</span></div>
</div>
<div class="info-panel">
<h3 id="toggle-paths">🔥 Top Hop Nodes <span id="paths-status">(visible)</span></h3>
<div id="node-list"></div>
</div>
<div class="playback-panel">
<button class="playback-btn" id="btn-play" title="Play history">▶️</button>
<button class="playback-btn live" id="btn-live" title="Go live">🔴 LIVE</button>
<input type="range" class="playback-slider" id="timeline" min="0" max="0" value="0">
<div class="playback-time live" id="playback-time">● LIVE</div>
<div class="playback-info"><span class="snapshot-count" id="snapshot-count">0</span> snaps</div>
<div class="threshold-control">
<label>Filter:</label>
<input type="range" class="threshold-slider" id="playback-threshold" min="1" max="48" value="48">
<span class="threshold-value" id="playback-threshold-value">ALL</span>
</div>
</div>
<script>
const map = L.map('map', { center: [52.5, -1], zoom: 7, zoomControl: true, zoomSnap: 0.25, zoomDelta: 0.5, wheelPxPerZoomLevel: 120 });
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: '© OpenStreetMap' }).addTo(map);
let hopData = [], pathData = [], heatLayer = null, markers = [], pathLines = [];
let selectedNode = null, markersVisible = true;
// Playback state - loaded from server
let snapshots = [], isPlaying = false, playbackIndex = 0, playbackInterval = null, liveMode = true;
const PLAYBACK_SPEED = 400;
function loadSnapshots() {
fetch('/local/meshcore_heatmap_history.json?t=' + Date.now())
.then(r => r.json())
.then(data => {
if (data.snapshots && Array.isArray(data.snapshots)) {
snapshots = data.snapshots;
updateSnapshotCount();
}
})
.catch(e => {});
}
function updateSnapshotCount() {
document.getElementById('snapshot-count').textContent = snapshots.length;
document.getElementById('timeline').max = Math.max(0, snapshots.length - 1);
if (liveMode && snapshots.length > 0) {
document.getElementById('timeline').value = snapshots.length - 1;
}
}
function formatTime(ts) {
const d = new Date(ts * 1000);
return d.toLocaleString('en-GB', { day: '2-digit', month: '2-digit', hour: '2-digit', minute: '2-digit' });
}
document.getElementById('btn-play').addEventListener('click', function() {
if (snapshots.length === 0) return;
if (isPlaying) {
isPlaying = false;
clearInterval(playbackInterval);
this.textContent = '▶️';
} else {
isPlaying = true;
liveMode = false;
this.textContent = '⏸️';
document.getElementById('btn-live').classList.remove('live');
document.getElementById('playback-time').classList.remove('live');
if (playbackIndex >= snapshots.length - 1) playbackIndex = 0;
playbackInterval = setInterval(() => {
playbackIndex++;
if (playbackIndex >= snapshots.length) {
isPlaying = false;
clearInterval(playbackInterval);
document.getElementById('btn-play').textContent = '▶️';
playbackIndex = snapshots.length - 1;
}
document.getElementById('timeline').value = playbackIndex;
displaySnapshot(playbackIndex);
}, PLAYBACK_SPEED);
}
});
document.getElementById('btn-live').addEventListener('click', goLive);
function goLive() {
isPlaying = false;
liveMode = true;
clearInterval(playbackInterval);
document.getElementById('btn-play').textContent = '▶️';
document.getElementById('btn-live').classList.add('live');
document.getElementById('playback-time').textContent = '● LIVE';
document.getElementById('playback-time').classList.add('live');
if (snapshots.length > 0) document.getElementById('timeline').value = snapshots.length - 1;
fetchLiveData();
}
document.getElementById('timeline').addEventListener('input', function() {
if (snapshots.length === 0) return;
liveMode = false;
isPlaying = false;
clearInterval(playbackInterval);
document.getElementById('btn-play').textContent = '▶️';
document.getElementById('btn-live').classList.remove('live');
document.getElementById('playback-time').classList.remove('live');
playbackIndex = parseInt(this.value);
displaySnapshot(playbackIndex);
});
// Get threshold from Home Assistant (read from live data file)
let currentThresholdHours = 4; // Default for live mode
let playbackThresholdHours = 48; // Default for playback (48 = show all)
function loadThreshold() {
fetch('/local/meshcore_heatmap_data.json?t=' + Date.now())
.then(r => r.json())
.then(data => {
if (data.threshold_hours) {
currentThresholdHours = data.threshold_hours;
if (liveMode) {
document.getElementById('threshold-hours').textContent = currentThresholdHours;
}
}
}).catch(e => {});
}
// Playback threshold slider
document.getElementById('playback-threshold').addEventListener('input', function() {
playbackThresholdHours = parseInt(this.value);
const display = playbackThresholdHours >= 48 ? 'ALL' : playbackThresholdHours + 'h';
document.getElementById('playback-threshold-value').textContent = display;
if (!liveMode && snapshots.length > 0) {
displaySnapshot(playbackIndex);
}
});
function filterNodesByThreshold(nodes, snapshotTimestamp) {
if (!nodes || nodes.length === 0) return [];
// If threshold is 48+ (ALL), return all nodes
if (playbackThresholdHours >= 48) {
return nodes;
}
// If nodes don't have last_used timestamps, return all (old format data)
const hasTimestamps = nodes.some(n => n.last_used !== undefined && n.last_used > 0);
if (!hasTimestamps) {
return nodes;
}
const thresholdSeconds = playbackThresholdHours * 3600;
const cutoff = snapshotTimestamp - thresholdSeconds;
return nodes.filter(n => (n.last_used || 0) >= cutoff);
}
function displaySnapshot(index) {
if (index < 0 || index >= snapshots.length) return;
const snapshot = snapshots[index];
const snapshotTime = snapshot.timestamp;
// Filter nodes by playback threshold setting
hopData = filterNodesByThreshold(snapshot.nodes || [], snapshotTime);
pathData = snapshot.paths || [];
document.getElementById('playback-time').textContent = formatTime(snapshotTime);
const thresholdDisplay = playbackThresholdHours >= 48 ? 'ALL' : playbackThresholdHours;
document.getElementById('threshold-hours').textContent = thresholdDisplay;
updateMap(false);
}
function getColor(ratio) {
if (ratio < 0.2) return '#0000ff';
if (ratio < 0.4) return '#00ffff';
if (ratio < 0.6) return '#00ff00';
if (ratio < 0.8) return '#ffff00';
return '#ff0000';
}
function toggleMarkers() {
markersVisible = !markersVisible;
markers.forEach(m => m.setStyle({ fillOpacity: markersVisible ? 0.9 : 0, opacity: markersVisible ? 1 : 0 }));
document.getElementById('paths-status').textContent = markersVisible ? '(visible)' : '(hidden)';
}
document.getElementById('toggle-paths').addEventListener('click', toggleMarkers);
function highlightNodePaths(nodeName) {
selectedNode = selectedNode === nodeName ? null : nodeName;
document.querySelectorAll('.node-item').forEach(item => {
item.classList.toggle('active', item.dataset.nodeName === selectedNode);
});
pathLines.forEach(line => {
if (selectedNode === null) line.setStyle({ opacity: 0 });
else if (line.pathNodes && line.pathNodes.includes(selectedNode)) {
line.setStyle({ opacity: 0.8, dashArray: '8, 8', weight: 3 });
line.bringToFront();
}
else line.setStyle({ opacity: 0 });
});
}
function updateMap(fitBounds = false) {
if (heatLayer) map.removeLayer(heatLayer);
markers.forEach(m => map.removeLayer(m));
markers = [];
pathLines.forEach(l => map.removeLayer(l));
pathLines = [];
if (hopData.length === 0) return;
const maxUses = Math.max(...hopData.map(d => d.use_count), 1);
const totalTraffic = hopData.reduce((sum, d) => sum + d.use_count, 0);
document.getElementById('node-count').textContent = hopData.length;
document.getElementById('path-count').textContent = pathData.length;
document.getElementById('total-traffic').textContent = totalTraffic;
document.getElementById('max-uses').textContent = maxUses;
// Draw paths
if (pathData && pathData.length > 0) {
const maxHops = Math.max(...pathData.map(p => p.hops || 1), 1);
pathData.forEach(path => {
const coords = path.coords || path.coordinates;
if (!coords || coords.length < 2) return;
const latlngs = coords.map(c => [c.lat, c.lon]);
const ratio = 1 - ((path.hops - 2) / Math.max(maxHops - 2, 1));
const color = getColor(Math.max(0, Math.min(1, ratio)));
const polyline = L.polyline(latlngs, { color: color, weight: 3, opacity: 0, dashArray: '8, 8' }).addTo(map);
polyline.pathNodes = coords.map(c => c.name);
polyline.sender = path.sender;
polyline.bindPopup(`<div style="text-align:center;"><strong>${path.sender}</strong><br><span style="color:${color};font-size:18px;font-weight:bold;">${path.hops}</span> hops</div>`);
pathLines.push(polyline);
});
}
const heatData = hopData.map(node => [node.lat, node.lon, node.use_count / maxUses]);
heatLayer = L.heatLayer(heatData, { radius: 50, blur: 35, maxZoom: 10, max: 1.0, minOpacity: 0.3,
gradient: { 0.0: '#0000ff', 0.25: '#00ffff', 0.5: '#00ff00', 0.75: '#ffff00', 1.0: '#ff0000' }
}).addTo(map);
hopData.forEach(node => {
const ratio = node.use_count / maxUses;
const marker = L.circleMarker([node.lat, node.lon], { radius: 4, fillColor: getColor(ratio), color: '#000', weight: 1, opacity: markersVisible ? 1 : 0, fillOpacity: markersVisible ? 0.9 : 0 }).addTo(map);
marker.bindPopup(`<div style="text-align:center;"><strong>${node.name}</strong><br><span style="color:${getColor(ratio)};font-size:18px;font-weight:bold;">${node.use_count}</span> uses</div>`);
markers.push(marker);
});
const nodeList = document.getElementById('node-list');
const sortedNodes = [...hopData].sort((a, b) => b.use_count - a.use_count);
nodeList.innerHTML = sortedNodes.map(node => {
const color = getColor(node.use_count / maxUses);
return `<div class="node-item" data-node-name="${node.name}" onclick="highlightNodePaths('${node.name.replace(/'/g, "\\'")}')"><div class="node-dot" style="background:${color};"></div><span class="node-name" title="${node.name}">${node.name}</span><span class="node-count">${node.use_count}</span></div>`;
}).join('');
if (fitBounds && hopData.length > 1) map.fitBounds(L.latLngBounds(hopData.map(d => [d.lat, d.lon])), { padding: [50, 50] });
}
function fetchLiveData() {
fetch('/local/meshcore_heatmap_data.json?t=' + Date.now())
.then(r => r.json())
.then(data => {
if (data.nodes && Array.isArray(data.nodes)) {
if (data.threshold_hours) document.getElementById('threshold-hours').textContent = data.threshold_hours;
if (liveMode) {
hopData = data.nodes;
pathData = data.paths || [];
updateMap(markers.length === 0);
}
}
}).catch(e => {});
}
// Load snapshots from server
loadSnapshots();
loadThreshold();
setInterval(loadSnapshots, 30000); // Check every 30 seconds
setInterval(loadThreshold, 60000); // Update threshold every minute
// Initial live data
fetch('/local/meshcore_heatmap_data.json')
.then(r => r.json())
.then(data => {
if (data.nodes && Array.isArray(data.nodes)) {
hopData = data.nodes;
pathData = data.paths || [];
if (data.threshold_hours) document.getElementById('threshold-hours').textContent = data.threshold_hours;
updateMap(true);
}
}).catch(e => {});
setInterval(fetchLiveData, 10000);
</script>
</body>
</html>
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More