Rupert  Beatty

Rupert Beatty

1676901660

Skeleton: An easy way to create sliding CAGradientLayer animations!

Skeleton

Skeleton is an easy way to create sliding CAGradientLayer animations! It works great for creating skeleton screens:

skeleton-logo-animation.gif

👩‍💻 Usage

The entire library comes down to just one public-facing extension:

public extension CAGradientLayer {
  public func slide(to dir: Direction, group: ((CAAnimationGroup) -> Void) = { _ in })
  public func stopSliding()
}

You can check out the example and the documentation for more.

📚 Example

To run the example project, clone the repo, and run pod install from the Example directory first.

🛠 Installation

Skeleton is available through CocoaPods. To install it, simply add the following line to your Podfile:

pod "Skeleton"

Skeleton is also available through Carthage. Add this to your Cartfile:

github "gonzalonunez/Skeleton" ~> 0.4.0

Download Details:

Author: Gonzalonunez
Source Code: https://github.com/gonzalonunez/Skeleton 
License: MIT license

#swift #ios #skeleton #loader #gradient 

Skeleton: An easy way to create sliding CAGradientLayer animations!
Rupert  Beatty

Rupert Beatty

1673345400

Windless Makes It Easy to Implement invisible Layout Loading View

Windless

Windless makes it easy to implement invisible layout loading view.

basic.giftable.gifcollection.gif

Requirements

  • iOS 8.0+
  • Xcode 9.0+
  • Swift 4.0+

Installation

CocoaPods

CocoaPods is a dependency manager for Cocoa projects. You can install it with the following command:

$ gem install cocoapods

CocoaPods 1.1+ is required to build Windless 4.0+.

To integrate Windless into your Xcode project using CocoaPods, specify it in your Podfile:

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'
use_frameworks!

target '<Your Target Name>' do
    pod 'Windless', '~> 0.1.5'
end

Then, run the following command:

$ pod install

Carthage

Carthage is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks.

You can install Carthage with Homebrew using the following command:

$ brew update
$ brew install carthage

To integrate Windless into your Xcode project using Carthage, specify it in your Cartfile:

github "Interactive-Studio/Windless" ~> 0.1.5

Run carthage update to build the framework and drag the built Windless.framework into your Xcode project.

Manually

If you prefer not to use either of the aforementioned dependency managers, you can integrate Windless into your project manually.


Usage

Code

import Windless

class ViewController: UIViewController {

    lazy var contentsView = UIView()
    
    var subView1 = UIView()
    var subView2 = UIView()

    override func viewDidLoad() {
        super.viewDidLoad()

        self.view.addSubview(contentsView)
        contentsView.addSubview(subView1)
        contentsView.addSubview(subView2)
        
        // start
        contentsView.windless
                .setupWindlessableViews([subView1, subView2])
                .start()
                
        // stop
        contentsView.windless.end()
    }

}

Storyboard, Xib

If you use Storyboard or xib, you only need to set the isWindlessable flag to true for the views you want to show as fake in the view inspector of the view, and you do not have to pass the view through the setupWindlessableViews method.

import Windless

class ViewController: UIViewController {

    @IBOutlet weak var contentsView: UIView!

    override func viewDidLoad() {
        super.viewDidLoad()

        contentsView.windless.start()
    }
}

Multiline

Depending on the lineHeight value and the spacing value, UILabel and UITextView will reconstruct the layout when the windless animation runs.

public protocol CanBeMultipleLines {

    var lineHeight: CGFloat { get set }

    var spacing: CGFloat { get set }
}
ConfigurationResult

Custom Options

There are several customizable options in Windless.

public class WindlessConfiguration {
    
    /// The direction of windless animation. Defaults to rightDiagonal.
    public var direction: WindlessDirection = .rightDiagonal
    
    /// The speed of windless animation. Defaults to 1.
    public var speed: Float = 1
    
    /// The duration of the fade used when windless begins. Defaults to 0.
    public var beginTime: CFTimeInterval = 0
    
    /// The time interval windless in seconds. Defaults to 4.
    public var duration: CFTimeInterval = 4
    
    /// The time interval between windless in seconds. Defaults to 2.
    public var pauseDuration: CFTimeInterval = 2
    
    /// gradient animation timingFunction default easeOut
    public var timingFuction: CAMediaTimingFunction = .easeOut
    
    /// gradient layer center color default .lightGray
    public var animationLayerColor: UIColor = .lightGray
    
    /// Mask layer background color default .groupTableViewBackground
    public var animationBackgroundColor: UIColor = .groupTableViewBackground
    
    /// The opacity of the content while it is windless. Defaults to 0.8.
    public var animationLayerOpacity: CGFloat = 0.8
}

To set the options, use the apply method as shown below.

import Windless

class ViewController: UIViewController {

    @IBOutlet weak var contentsView: UIView!

    override func viewDidLoad() {
        super.viewDidLoad()

        contentsView.windless
            .apply {
                $0.beginTime = 1
                $0.pauseDuration = 2
                $0.duration = 3
                $0.animationLayerOpacity = 0.5
            }
            .start()
    }
}

If you want to know more detailed usage, please refer to Example.

Looks

The isWindlessable value determines how the loading view looks. The images below show how the loading screen will look according to the isWindlessable value.

isWindlessable= 🌀

ConfigurationResult

Communication

  • If you found a bug, open an issue.
  • If you have a feature request, open an issue.
  • If you want to contribute, submit a pull request.

Credits

Download Details:

Author: ParkGwangBeom
Source Code: https://github.com/ParkGwangBeom/Windless 
License: MIT license

#swift #ios #skeleton #animation #loading 

Windless Makes It Easy to Implement invisible Layout Loading View

PrimeReact /PrimefacesUIを使用してReactJSでスケルトンを作成する

PRIMEREACT UIフレームワークには、すべてのUI要件をスタイリッシュに実装するのに役立つ最高品質の80を超えるReactUIコンポーネントがあります。

Skeletonは、データが読み込まれる前にコンテンツのプレースホルダープレビューを表示して、読み込み時のフラストレーションを軽減します。

前提条件

  • Javascript
  • Reactjsの基本的な知識
  • Node.js
  • VS Code、Visual Studio

以下のことをカバーします、

  • Reactアプリケーションを作成する
  • Primefaceのインストール
  • ReactjsでPrimefaceのスケルトンを適用する方法

ステップ1

次のコマンドを使用してreactプロジェクトを作成します

npx create-react-app prime-app
cd prime-app
npm start

ステップ2

PrimeReactをインストールするには、以下のコマンドを実行します

npm install primereact primeicons

下の画像に従ってファイルを作成します

ステップ3

App.jsに以下のコードを追加します

import logo from './logo.svg';
import './App.css';
import React, { useState, useEffect } from 'react';
import { AutoComplete } from 'primereact/autocomplete';
import { CountryService } from '../src/CountryService';
import { Skeleton } from 'primereact/skeleton';
import { DataTable } from 'primereact/datatable';
import { Column } from 'primereact/column';


function App() {

    const [countries, setCountries] = useState([]);
    const [selectedCountry1, setSelectedCountry1] = useState(null);
    const [selectedCountry2, setSelectedCountry2] = useState(null);
    const [selectedCity, setSelectedCity] = useState(null);
    const [selectedCountries, setSelectedCountries] = useState(null);
    const [selectedItem, setSelectedItem] = useState(null);
    const [filteredCountries, setFilteredCountries] = useState(null);
    const [filteredCities, setFilteredCities] = useState(null);
    const [filteredItems, setFilteredItems] = useState(null);
    const countryservice = new CountryService();
    const groupedCities = [
        {
            label: 'Germany', code: 'DE',
            items: [
                { label: 'Berlin', value: 'Berlin' },
                { label: 'Frankfurt', value: 'Frankfurt' },
                { label: 'Hamburg', value: 'Hamburg' },
                { label: 'Munich', value: 'Munich' }
            ]
        },
        {
            label: 'USA', code: 'US',
            items: [
                { label: 'Chicago', value: 'Chicago' },
                { label: 'Los Angeles', value: 'Los Angeles' },
                { label: 'New York', value: 'New York' },
                { label: 'San Francisco', value: 'San Francisco' }
            ]
        },
        {
            label: 'Japan', code: 'JP',
            items: [
                { label: 'Kyoto', value: 'Kyoto' },
                { label: 'Osaka', value: 'Osaka' },
                { label: 'Tokyo', value: 'Tokyo' },
                { label: 'Yokohama', value: 'Yokohama' }
            ]
        }
    ];


    const products = Array.from({ length: 5 });

    const bodyTemplate = () => {
        return <Skeleton></Skeleton>
    }


    const items = Array.from({ length: 100000 }).map((_, i) => ({ label: `Item #${i}`, value: i }));

    useEffect(() => {

        debugger
        setCountries(countryservice.getCountries())
    }, []); // eslint-disable-line react-hooks/exhaustive-deps

    const searchCountry = (event) => {
        setTimeout(() => {
            let _filteredCountries;
            if (!event.query.trim().length) {
                _filteredCountries = [...countries];
            }
            else {
                _filteredCountries = countries.filter((country) => {
                    return country.name.toLowerCase().startsWith(event.query.toLowerCase());
                });
            }

            setFilteredCountries(_filteredCountries);
        }, 250);
    }

    const searchCity = (event) => {
        let query = event.query;
        let _filteredCities = [];

        for (let country of groupedCities) {
            let filteredItems = country.items.filter((item) => item.label.toLowerCase().indexOf(query.toLowerCase()) !== -1);
            if (filteredItems && filteredItems.length) {
                _filteredCities.push({ ...country, ...{ items: filteredItems } });
            }
        }

        setFilteredCities(_filteredCities)
    }

    const searchItems = (event) => {
        //in a real application, make a request to a remote url with the query and return filtered results, for demo we filter at client side
        let query = event.query;
        let _filteredItems = [];

        for (let i = 0; i < items.length; i++) {
            let item = items[i];
            if (item.label.toLowerCase().indexOf(query.toLowerCase()) === 0) {
                _filteredItems.push(item);
            }
        }

        setFilteredItems(_filteredItems);
    }

    const itemTemplate = (item) => {
        return (
            <div className="country-item">
                <img alt={item.name} src={`images/flag/flag_placeholder.png`} onError={(e) => e.target.src = 'https://www.primefaces.org/wp-content/uploads/2020/05/placeholder.png'} className={`flag flag-${item.code.toLowerCase()}`} />
                <div>{item.name}</div>
            </div>
        );
    }
    const groupedItemTemplate = (item) => {
        return (
            <div className="flex align-items-center country-item">
                <img alt={item.name} src={`images/flag/flag_placeholder.png`} onError={(e) => e.target.src = 'https://www.primefaces.org/wp-content/uploads/2020/05/placeholder.png'} className={`flag flag-${item.code.toLowerCase()}`} />
                <div>{item.label}</div>
            </div>
        );
    }
    return (

        <div>
            <div className="card">
                <div className="grid formgrid">
                    <div className="field col-12 md:col-6">
                        <h5>Rectangle</h5>
                        <Skeleton className="mb-2"></Skeleton>
                        <Skeleton width="10rem" className="mb-2"></Skeleton>
                        <Skeleton width="5rem" className="mb-2"></Skeleton>
                        <Skeleton height="2rem" className="mb-2"></Skeleton>
                        <Skeleton width="10rem" height="4rem"></Skeleton>
                    </div>
                    <div className="field col-12 md:col-6">
                        <h5>Rounded</h5>
                        <Skeleton className="mb-2" borderRadius="16px"></Skeleton>
                        <Skeleton width="10rem" className="mb-2" borderRadius="16px"></Skeleton>
                        <Skeleton width="5rem" borderRadius="16px" className="mb-2"></Skeleton>
                        <Skeleton height="2rem" className="mb-2" borderRadius="16px"></Skeleton>
                        <Skeleton width="10rem" height="4rem" borderRadius="16px"></Skeleton>
                    </div>
                    <div className="field col-12 md:col-6">
                        <h5 className="mt-3">Square</h5>
                        <div className="flex align-items-end">
                            <Skeleton size="2rem" className="mr-2"></Skeleton>
                            <Skeleton size="3rem" className="mr-2"></Skeleton>
                            <Skeleton size="4rem" className="mr-2"></Skeleton>
                            <Skeleton size="5rem"></Skeleton>
                        </div>
                    </div>
                    <div className="field col-12 md:col-6">
                        <h5 className="mt-3">Circle</h5>
                        <div className="flex align-items-end">
                            <Skeleton shape="circle" size="2rem" className="mr-2"></Skeleton>
                            <Skeleton shape="circle" size="3rem" className="mr-2"></Skeleton>
                            <Skeleton shape="circle" size="4rem" className="mr-2"></Skeleton>
                            <Skeleton shape="circle" size="5rem"></Skeleton>
                        </div>
                    </div>
                </div>
            </div>

            <div className="card">
                <div className="grid formgrid">
                    <div className="field col-12 md:col-6 md:pr-6 pr-0">
                        <h5>Card</h5>
                        <div className="custom-skeleton p-4">
                            <div className="flex mb-3">
                                <Skeleton shape="circle" size="4rem" className="mr-2"></Skeleton>
                                <div>
                                    <Skeleton width="10rem" className="mb-2"></Skeleton>
                                    <Skeleton width="5rem" className="mb-2"></Skeleton>
                                    <Skeleton height=".5rem"></Skeleton>
                                </div>
                            </div>
                            <Skeleton width="100%" height="150px"></Skeleton>
                            <div className="flex justify-content-between mt-3">
                                <Skeleton width="4rem" height="2rem"></Skeleton>
                                <Skeleton width="4rem" height="2rem"></Skeleton>
                            </div>
                        </div>
                    </div>

                    <div className="field col-12 md:col-6">
                        <h5>List</h5>
                        <div className="custom-skeleton p-4">
                            <ul className="m-0 p-0">
                                <li className="mb-3">
                                    <div className="flex">
                                        <Skeleton shape="circle" size="4rem" className="mr-2"></Skeleton>
                                        <div style={{ flex: '1' }}>
                                            <Skeleton width="100%" className="mb-2"></Skeleton>
                                            <Skeleton width="75%"></Skeleton>
                                        </div>
                                    </div>
                                </li>
                                <li className="mb-3">
                                    <div className="flex">
                                        <Skeleton shape="circle" size="4rem" className="mr-2"></Skeleton>
                                        <div style={{ flex: '1' }}>
                                            <Skeleton width="100%" className="mb-2"></Skeleton>
                                            <Skeleton width="75%"></Skeleton>
                                        </div>
                                    </div>
                                </li>
                                <li className="mb-3">
                                    <div className="flex">
                                        <Skeleton shape="circle" size="4rem" className="mr-2"></Skeleton>
                                        <div style={{ flex: '1' }}>
                                            <Skeleton width="100%" className="mb-2"></Skeleton>
                                            <Skeleton width="75%"></Skeleton>
                                        </div>
                                    </div>
                                </li>
                                <li>
                                    <div className="flex">
                                        <Skeleton shape="circle" size="4rem" className="mr-2"></Skeleton>
                                        <div style={{ flex: '1' }}>
                                            <Skeleton width="100%" className="mb-2"></Skeleton>
                                            <Skeleton width="75%"></Skeleton>
                                        </div>
                                    </div>
                                </li>
                            </ul>
                        </div>
                    </div>
                </div>

                <h5>DataTable</h5>
                <DataTable value={products} className="p-datatable-striped">
                    <Column field="code" header="Code" style={{ width: '25%' }} body={bodyTemplate}></Column>
                    <Column field="name" header="Name" style={{ width: '25%' }} body={bodyTemplate}></Column>
                    <Column field="category" header="Category" style={{ width: '25%' }} body={bodyTemplate}></Column>
                    <Column field="quantity" header="Quantity" style={{ width: '25%' }} body={bodyTemplate}></Column>
                </DataTable>
            </div>
        </div>
    );
}
export default App;

ステップ4

以下のコードをindex.htmlに追加します

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta
      name="description"
      content="Web site created using create-react-app"
    />
    <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
    <!--
      manifest.json provides metadata used when your web app is installed on a
      user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
    -->
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <link rel="stylesheet" href="https://unpkg.com/primeicons@5.0.0/primeicons.css">

    <!--
      Notice the use of %PUBLIC_URL% in the tags above.
      It will be replaced with the URL of the `public` folder during the build.
      Only files inside the `public` folder can be referenced from the HTML.

      Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
      work correctly both with client-side routing and a non-root public URL.
      Learn how to configure a non-root public URL by running `npm run build`.
    -->
    <title>React App</title>
  </head>
  <body>

    <script src="https://unpkg.com/primereact/core/core.min.js"></script>
    <script src="https://unpkg.com/primereact/skeleton/skeleton.min.js"></script>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
    <!--
      This HTML file is a template.
      If you open it directly in the browser, you will see an empty page.

      You can add webfonts, meta tags, or analytics to this file.
      The build step will place the bundled scripts into the <body> tag.

      To begin the development, run `npm start` or `yarn start`.
      To create a production bundle, use `npm run build` or `yarn build`.
    -->
  </body>
</html>

ステップ5

App.cssに以下のコードを追加します

.App {
  text-align: center;
}
.App-logo {
  height: 40vmin;
  pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
  .App-logo {
    animation: App-logo-spin infinite 20s linear;
  }
}
.App-header {
  background-color: #282c34;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  font-size: calc(10px + 2vmin);
  color: white;
}
.App-link {
  color: #61dafb;
}
@keyframes App-logo-spin {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}
.custom-skeleton {
  border: 1px solid var(--surface-d);
  border-Radius: 4px;
}
.custom-skeleton ul {
  list-style: none;
}

ステップ6

以下のコードをCountryService.jsに追加します

import data from './contires.json';
export class CountryService {
 getCountries() {
      const result = [];
      data.map((datas)=>{
      result.push(datas)
   });
  return result;
}

ステップ7

package.jsonに次のコードを追加します

{
  "name": "prime-demo",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^5.16.4",
    "@testing-library/react": "^13.3.0",
    "@testing-library/user-event": "^13.5.0",
    "primeicons": "^5.0.0",
    "primereact": "^8.1.1",
    "react": "^18.1.0",
    "react-dom": "^18.1.0",
    "react-redux": "^8.0.2",
    "react-scripts": "^2.1.3",
    "redux": "^4.2.0",
    "web-vitals": "^2.1.4",
    "primeflex": "^3.1.0",
    "react-transition-group": "^4.4.1"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

ステップ8

以下のコマンドを実行します

npm i
npm start

ステップ9

Reactでスケルトンを作成する方法

概要

この記事では、reactプロジェクトを作成する方法、PrimeReact UIを設定する方法、PrimeReactUIのSkeletonUIウィジェットを追加する方法を学びました。

このストーリーは、もともとhttps://www.c-sharpcorner.com/article/how-to-create-skeleton-in-react-js-using-primereactprimefaces-ui/で公開されました

#react #skeleton #primereact #primefaces 

PrimeReact /PrimefacesUIを使用してReactJSでスケルトンを作成する
Saul  Alaniz

Saul Alaniz

1655001720

Cómo Crear Un Esqueleto En React JS Usuario De PrimeReact/Primefaces

El marco de interfaz de usuario PRIMEREACT tiene más de 80 componentes de interfaz de usuario React con una calidad de primer nivel para ayudarlo a implementar todos sus requisitos de interfaz de usuario con estilo.

Skeleton es mostrar una vista previa de marcador de posición de su contenido antes de que se carguen los datos para reducir la frustración del tiempo de carga.

condiciones previas

  • JavaScript
  • Conocimientos básicos de React js
  • Nodo.js
  • Código VS, estudio visual

Cubrimos las siguientes cosas,

  • Crear aplicación React
  • Instalación de Primeface
  • Cómo aplicar Skeleton of Primeface en React js

Paso 1

Cree un proyecto de reacción usando el siguiente comando

npx create-react-app prime-app
cd prime-app
npm start

Paso 2

Ejecute el siguiente comando para instalar PrimeReact

npm install primereact primeicons

Cree los archivos de acuerdo con la imagen de abajo.

Paso 3

Agregue el siguiente código en App.js

import logo from './logo.svg';
import './App.css';
import React, { useState, useEffect } from 'react';
import { AutoComplete } from 'primereact/autocomplete';
import { CountryService } from '../src/CountryService';
import { Skeleton } from 'primereact/skeleton';
import { DataTable } from 'primereact/datatable';
import { Column } from 'primereact/column';


function App() {

    const [countries, setCountries] = useState([]);
    const [selectedCountry1, setSelectedCountry1] = useState(null);
    const [selectedCountry2, setSelectedCountry2] = useState(null);
    const [selectedCity, setSelectedCity] = useState(null);
    const [selectedCountries, setSelectedCountries] = useState(null);
    const [selectedItem, setSelectedItem] = useState(null);
    const [filteredCountries, setFilteredCountries] = useState(null);
    const [filteredCities, setFilteredCities] = useState(null);
    const [filteredItems, setFilteredItems] = useState(null);
    const countryservice = new CountryService();
    const groupedCities = [
        {
            label: 'Germany', code: 'DE',
            items: [
                { label: 'Berlin', value: 'Berlin' },
                { label: 'Frankfurt', value: 'Frankfurt' },
                { label: 'Hamburg', value: 'Hamburg' },
                { label: 'Munich', value: 'Munich' }
            ]
        },
        {
            label: 'USA', code: 'US',
            items: [
                { label: 'Chicago', value: 'Chicago' },
                { label: 'Los Angeles', value: 'Los Angeles' },
                { label: 'New York', value: 'New York' },
                { label: 'San Francisco', value: 'San Francisco' }
            ]
        },
        {
            label: 'Japan', code: 'JP',
            items: [
                { label: 'Kyoto', value: 'Kyoto' },
                { label: 'Osaka', value: 'Osaka' },
                { label: 'Tokyo', value: 'Tokyo' },
                { label: 'Yokohama', value: 'Yokohama' }
            ]
        }
    ];


    const products = Array.from({ length: 5 });

    const bodyTemplate = () => {
        return <Skeleton></Skeleton>
    }


    const items = Array.from({ length: 100000 }).map((_, i) => ({ label: `Item #${i}`, value: i }));

    useEffect(() => {

        debugger
        setCountries(countryservice.getCountries())
    }, []); // eslint-disable-line react-hooks/exhaustive-deps

    const searchCountry = (event) => {
        setTimeout(() => {
            let _filteredCountries;
            if (!event.query.trim().length) {
                _filteredCountries = [...countries];
            }
            else {
                _filteredCountries = countries.filter((country) => {
                    return country.name.toLowerCase().startsWith(event.query.toLowerCase());
                });
            }

            setFilteredCountries(_filteredCountries);
        }, 250);
    }

    const searchCity = (event) => {
        let query = event.query;
        let _filteredCities = [];

        for (let country of groupedCities) {
            let filteredItems = country.items.filter((item) => item.label.toLowerCase().indexOf(query.toLowerCase()) !== -1);
            if (filteredItems && filteredItems.length) {
                _filteredCities.push({ ...country, ...{ items: filteredItems } });
            }
        }

        setFilteredCities(_filteredCities)
    }

    const searchItems = (event) => {
        //in a real application, make a request to a remote url with the query and return filtered results, for demo we filter at client side
        let query = event.query;
        let _filteredItems = [];

        for (let i = 0; i < items.length; i++) {
            let item = items[i];
            if (item.label.toLowerCase().indexOf(query.toLowerCase()) === 0) {
                _filteredItems.push(item);
            }
        }

        setFilteredItems(_filteredItems);
    }

    const itemTemplate = (item) => {
        return (
            <div className="country-item">
                <img alt={item.name} src={`images/flag/flag_placeholder.png`} onError={(e) => e.target.src = 'https://www.primefaces.org/wp-content/uploads/2020/05/placeholder.png'} className={`flag flag-${item.code.toLowerCase()}`} />
                <div>{item.name}</div>
            </div>
        );
    }
    const groupedItemTemplate = (item) => {
        return (
            <div className="flex align-items-center country-item">
                <img alt={item.name} src={`images/flag/flag_placeholder.png`} onError={(e) => e.target.src = 'https://www.primefaces.org/wp-content/uploads/2020/05/placeholder.png'} className={`flag flag-${item.code.toLowerCase()}`} />
                <div>{item.label}</div>
            </div>
        );
    }
    return (

        <div>
            <div className="card">
                <div className="grid formgrid">
                    <div className="field col-12 md:col-6">
                        <h5>Rectangle</h5>
                        <Skeleton className="mb-2"></Skeleton>
                        <Skeleton width="10rem" className="mb-2"></Skeleton>
                        <Skeleton width="5rem" className="mb-2"></Skeleton>
                        <Skeleton height="2rem" className="mb-2"></Skeleton>
                        <Skeleton width="10rem" height="4rem"></Skeleton>
                    </div>
                    <div className="field col-12 md:col-6">
                        <h5>Rounded</h5>
                        <Skeleton className="mb-2" borderRadius="16px"></Skeleton>
                        <Skeleton width="10rem" className="mb-2" borderRadius="16px"></Skeleton>
                        <Skeleton width="5rem" borderRadius="16px" className="mb-2"></Skeleton>
                        <Skeleton height="2rem" className="mb-2" borderRadius="16px"></Skeleton>
                        <Skeleton width="10rem" height="4rem" borderRadius="16px"></Skeleton>
                    </div>
                    <div className="field col-12 md:col-6">
                        <h5 className="mt-3">Square</h5>
                        <div className="flex align-items-end">
                            <Skeleton size="2rem" className="mr-2"></Skeleton>
                            <Skeleton size="3rem" className="mr-2"></Skeleton>
                            <Skeleton size="4rem" className="mr-2"></Skeleton>
                            <Skeleton size="5rem"></Skeleton>
                        </div>
                    </div>
                    <div className="field col-12 md:col-6">
                        <h5 className="mt-3">Circle</h5>
                        <div className="flex align-items-end">
                            <Skeleton shape="circle" size="2rem" className="mr-2"></Skeleton>
                            <Skeleton shape="circle" size="3rem" className="mr-2"></Skeleton>
                            <Skeleton shape="circle" size="4rem" className="mr-2"></Skeleton>
                            <Skeleton shape="circle" size="5rem"></Skeleton>
                        </div>
                    </div>
                </div>
            </div>

            <div className="card">
                <div className="grid formgrid">
                    <div className="field col-12 md:col-6 md:pr-6 pr-0">
                        <h5>Card</h5>
                        <div className="custom-skeleton p-4">
                            <div className="flex mb-3">
                                <Skeleton shape="circle" size="4rem" className="mr-2"></Skeleton>
                                <div>
                                    <Skeleton width="10rem" className="mb-2"></Skeleton>
                                    <Skeleton width="5rem" className="mb-2"></Skeleton>
                                    <Skeleton height=".5rem"></Skeleton>
                                </div>
                            </div>
                            <Skeleton width="100%" height="150px"></Skeleton>
                            <div className="flex justify-content-between mt-3">
                                <Skeleton width="4rem" height="2rem"></Skeleton>
                                <Skeleton width="4rem" height="2rem"></Skeleton>
                            </div>
                        </div>
                    </div>

                    <div className="field col-12 md:col-6">
                        <h5>List</h5>
                        <div className="custom-skeleton p-4">
                            <ul className="m-0 p-0">
                                <li className="mb-3">
                                    <div className="flex">
                                        <Skeleton shape="circle" size="4rem" className="mr-2"></Skeleton>
                                        <div style={{ flex: '1' }}>
                                            <Skeleton width="100%" className="mb-2"></Skeleton>
                                            <Skeleton width="75%"></Skeleton>
                                        </div>
                                    </div>
                                </li>
                                <li className="mb-3">
                                    <div className="flex">
                                        <Skeleton shape="circle" size="4rem" className="mr-2"></Skeleton>
                                        <div style={{ flex: '1' }}>
                                            <Skeleton width="100%" className="mb-2"></Skeleton>
                                            <Skeleton width="75%"></Skeleton>
                                        </div>
                                    </div>
                                </li>
                                <li className="mb-3">
                                    <div className="flex">
                                        <Skeleton shape="circle" size="4rem" className="mr-2"></Skeleton>
                                        <div style={{ flex: '1' }}>
                                            <Skeleton width="100%" className="mb-2"></Skeleton>
                                            <Skeleton width="75%"></Skeleton>
                                        </div>
                                    </div>
                                </li>
                                <li>
                                    <div className="flex">
                                        <Skeleton shape="circle" size="4rem" className="mr-2"></Skeleton>
                                        <div style={{ flex: '1' }}>
                                            <Skeleton width="100%" className="mb-2"></Skeleton>
                                            <Skeleton width="75%"></Skeleton>
                                        </div>
                                    </div>
                                </li>
                            </ul>
                        </div>
                    </div>
                </div>

                <h5>DataTable</h5>
                <DataTable value={products} className="p-datatable-striped">
                    <Column field="code" header="Code" style={{ width: '25%' }} body={bodyTemplate}></Column>
                    <Column field="name" header="Name" style={{ width: '25%' }} body={bodyTemplate}></Column>
                    <Column field="category" header="Category" style={{ width: '25%' }} body={bodyTemplate}></Column>
                    <Column field="quantity" header="Quantity" style={{ width: '25%' }} body={bodyTemplate}></Column>
                </DataTable>
            </div>
        </div>
    );
}
export default App;

Paso 4

Agregue el siguiente código en index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta
      name="description"
      content="Web site created using create-react-app"
    />
    <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
    <!--
      manifest.json provides metadata used when your web app is installed on a
      user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
    -->
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <link rel="stylesheet" href="https://unpkg.com/primeicons@5.0.0/primeicons.css">

    <!--
      Notice the use of %PUBLIC_URL% in the tags above.
      It will be replaced with the URL of the `public` folder during the build.
      Only files inside the `public` folder can be referenced from the HTML.

      Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
      work correctly both with client-side routing and a non-root public URL.
      Learn how to configure a non-root public URL by running `npm run build`.
    -->
    <title>React App</title>
  </head>
  <body>

    <script src="https://unpkg.com/primereact/core/core.min.js"></script>
    <script src="https://unpkg.com/primereact/skeleton/skeleton.min.js"></script>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
    <!--
      This HTML file is a template.
      If you open it directly in the browser, you will see an empty page.

      You can add webfonts, meta tags, or analytics to this file.
      The build step will place the bundled scripts into the <body> tag.

      To begin the development, run `npm start` or `yarn start`.
      To create a production bundle, use `npm run build` or `yarn build`.
    -->
  </body>
</html>

Paso 5

Agregue el siguiente código en App.css

.App {
  text-align: center;
}
.App-logo {
  height: 40vmin;
  pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
  .App-logo {
    animation: App-logo-spin infinite 20s linear;
  }
}
.App-header {
  background-color: #282c34;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  font-size: calc(10px + 2vmin);
  color: white;
}
.App-link {
  color: #61dafb;
}
@keyframes App-logo-spin {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}
.custom-skeleton {
  border: 1px solid var(--surface-d);
  border-Radius: 4px;
}
.custom-skeleton ul {
  list-style: none;
}

Paso 6

Agregue el siguiente código en CountryService.js

import data from './contires.json';
export class CountryService {
 getCountries() {
      const result = [];
      data.map((datas)=>{
      result.push(datas)
   });
  return result;
}

Paso 7

Agregue el siguiente código en package.json

{
  "name": "prime-demo",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^5.16.4",
    "@testing-library/react": "^13.3.0",
    "@testing-library/user-event": "^13.5.0",
    "primeicons": "^5.0.0",
    "primereact": "^8.1.1",
    "react": "^18.1.0",
    "react-dom": "^18.1.0",
    "react-redux": "^8.0.2",
    "react-scripts": "^2.1.3",
    "redux": "^4.2.0",
    "web-vitals": "^2.1.4",
    "primeflex": "^3.1.0",
    "react-transition-group": "^4.4.1"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

Paso 8

Ejecute los siguientes comandos

npm i
npm start

Paso 9

Cómo crear un esqueleto en React

Resumen

En este artículo, aprendimos cómo crear un proyecto de reacción, configurar la interfaz de usuario de PrimeReact y agregar widgets de interfaz de usuario de esqueleto de la interfaz de usuario de PrimeReact.

Esta historia se publicó originalmente en https://www.c-sharpcorner.com/article/how-to-create-skeleton-in-react-js-using-primereactprimefaces-ui/

#react #skeleton #primereact #primefaces 

Cómo Crear Un Esqueleto En React JS Usuario De PrimeReact/Primefaces
Veronica  Roob

Veronica Roob

1653115680

Skeleton Application for Laminas API Tools

Laminas API Tools Skeleton Application

Requirements

Please see the composer.json file.

Installation

Via release tarball

Grab the latest release via the Laminas API Tools website and/or the releases page; each release has distribution tarballs and zipballs available.

Untar it:

$ tar xzf api-tools-skeleton-{version}.tgz

(Where {version} is the version you downloaded.)

Or unzip, if you chose the zipball:

$ unzip api-tools-skeleton-{version}.zip

(Where {version} is the version you downloaded.)

Via Composer (create-project)

You can use the create-project command from Composer to create the project in one go (you need to install composer):

$ curl -s https://getcomposer.org/installer | php -- --filename=composer
$ composer create-project -sdev laminas-api-tools/api-tools-skeleton path/to/install

Via Git (clone)

First, clone the repository:

# git clone https://github.com/laminas-api-tools/api-tools-skeleton.git # optionally, specify the directory in which to clone
$ cd path/to/install

At this point, you need to use Composer to install dependencies. Assuming you already have Composer:

$ composer install

All methods

Once you have the basic installation, you need to put it in development mode:

$ cd path/to/install
$ composer development-enable

Now, fire it up! Do one of the following:

  • Create a vhost in your web server that points the DocumentRoot to the public/ directory of the project
  • Fire up the built-in web server in PHP(note: do not use this for production!)

In the latter case, do the following:

$ cd path/to/install
$ php -S 0.0.0.0:8080 -ddisplay_errors=0 -t public public/index.php
# OR use the composer alias:
$ composer serve

You can then visit the site at http://localhost:8080/ - which will bring up a welcome page and the ability to visit the dashboard in order to create and inspect your APIs.

NOTE ABOUT USING APACHE

Apache forbids the character sequences %2F and %5C in URI paths. However, the Laminas API Tools Admin API uses these characters for a number of service endpoints. As such, if you wish to use the Admin UI and/or Admin API with Apache, you will need to configure your Apache vhost/project to allow encoded slashes:

AllowEncodedSlashes On

This change will need to be made in your server's vhost file (it cannot be added to .htaccess).

NOTE ABOUT OPCACHE

Disable all opcode caches when running the admin!

The admin cannot and will not run correctly when an opcode cache, such as APC or OpCache, is enabled. Laminas API Tools does not use a database to store configuration; instead, it uses PHP configuration files. Opcode caches will cache these files on first load, leading to inconsistencies as you write to them, and will typically lead to a state where the admin API and code become unusable.

The admin is a development tool, and intended for use a development environment. As such, you should likely disable opcode caching, regardless.

When you are ready to deploy your API to production, however, you can disable development mode, thus disabling the admin interface, and safely run an opcode cache again. Doing so is recommended for production due to the tremendous performance benefits opcode caches provide.

NOTE ABOUT DISPLAY_ERRORS

The display_errors php.ini setting is useful in development to understand what warnings, notices, and error conditions are affecting your application. However, they cause problems for APIs: APIs are typically a specific serialization format, and error reporting is usually in either plain text, or, with extensions like XDebug, in HTML. This breaks the response payload, making it unusable by clients.

For this reason, we recommend disabling display_errors when using the Laminas API Tools admin interface. This can be done using the -ddisplay_errors=0 flag when using the built-in PHP web server, or you can set it in your virtual host or server definition. If you disable it, make sure you have reasonable error log settings in place. For the built-in PHP web server, errors will be reported in the console itself; otherwise, ensure you have an error log file specified in your configuration.

display_errors should never be enabled in production, regardless.

Vagrant

If you prefer to develop with Vagrant, there is a basic vagrant recipe included with this project.

This recipe assumes that you already have Vagrant installed. The virtual machine will try to use localhost:8080 by default, so if you already have a server on this port of your host machine, you need to shut down the conflicting server first, or if you know how, you can reconfigure the ports in Vagrantfile.

Assuming you have Vagrant installed and assuming you have no port conflicts, you can bring up the Vagrant machine with the standard up command:

$ vagrant up

When the machine comes up, you can ssh to it with the standard ssh forward agent:

$ vagrant ssh

The web root is inside the shared directory, which is at /var/www; this is also the home directory for the vagrant issue, which will be the initial directory you land in once you connect via SSH.

The image installs composer during provisioning, meaning you can use it to install and update dependencies:

# Install dependencies:
$ vagrant ssh -c 'composer install'
# Update dependencies:
$ vagrant ssh -c 'composer update'

You can also manipulate development mode:

$ vagrant ssh -c 'composer development-enable'
$ vagrant ssh -c 'composer development-disable'
$ vagrant ssh -c 'composer development-status'

Vagrant and VirtualBox

The vagrant image is based on bento/ubuntu-16.04. If you are using VirtualBox as a provider, you will need:

  • Vagrant 1.8.5 or later
  • VirtualBox 5.0.26 or later

For vagrant documentation, please refer to vagrantup.com

Docker

If you develop or deploy using Docker, we provide configuration for you.

Prepare your development environment using docker compose:

$ git clone https://github.com/laminas-api-tools/api-tools-skeleton
$ cd api-tools-skeleton
$ docker-compose build
# Install dependencies via composer, if you haven't already:
$ docker-compose run api-tools composer install
# Enable development mode:
$ docker-compose run api-tools composer development-enable

Start the container:

$ docker-compose up

Access Laminas API Tools from http://localhost:8080/ or http://<boot2docker ip>:8080/ if on Windows or Mac.

You may also use the provided Dockerfile directly if desired.

Once installed, you can use the container to update dependencies:

$ docker-compose run api-tools composer update

Or to manipulate development mode:

$ docker-compose run api-tools composer development-enable
$ docker-compose run api-tools composer development-disable
$ docker-compose run api-tools composer development-status

QA Tools

The skeleton ships with minimal QA tooling by default, including laminas/laminas-test. We supply basic tests for the shipped Application\Controller\IndexController.

We also ship with configuration for phpcs. If you wish to add this QA tool, execute the following:

$ composer require --dev squizlabs/php_codesniffer

We provide aliases for each of these tools in the Composer configuration:

# Run CS checks:
$ composer cs-check
# Fix CS errors:
$ composer cs-fix
# Run PHPUnit tests:
$ composer test

Author: laminas-api-tools
Source Code: https://github.com/laminas-api-tools/api-tools-skeleton
License: BSD-3-Clause License

#php #api #skeleton 

Skeleton Application for Laminas API Tools
坂本  篤司

坂本 篤司

1651014000

より良いUXのためにCSSでスケルトンスクリーンを構築する

コンテンツローダー、スケルトンスクリーン、ゴースト要素、およびコンテンツプレースホルダー。これらは、今日調査するエフェクトに付けられた名前です。

Linkedin、Facebook、Youtube、Slackなどの多くの企業は、お気づきかもしれませんが、アプリやWebサイトでこの効果を使用しています。

開発者はウェブサイトをできるだけ早く読み込むことを望んでいますが、ページに大量のデータをレンダリングする必要がある場合があるため、スケルトン画面は優れたオプションです。

前提条件

この記事はあなたが持っていることを前提としています:

  • HTMLとCSS(SASS)の知識
  • JavaScriptの知識(ES6)

このプロジェクトではHTMLとSASSを使用します。SASSの使用を開始したい場合は、この初心者向けガイドを確認してください。

スケルトンスクリーンとは何ですか?

スケルトン画面は、データの読み込み中にWebサイトのレイアウトをシミュレートするアニメーションのプレースホルダーです。

一部のコンテンツが読み込まれていることをユーザーに通知し、さらに重要なことに、画像、テキスト、カードなど、何が読み込まれているかを示します。

これにより、ユーザーは、表示される前にどのタイプのコンテンツがロードされているかをすでに知っているため、Webサイトが高速であるという印象を与えることができます。これは、知覚パフォーマンスと呼ばれます。

FacebookとLinkedInのスケルトン画面の例を次に示します。

1-2

LinkedInのホームフィードの読み込み状態

2-2

Facebookのホームフィードの読み込み状態

さまざまな種類のスケルトンスクリーン

スケルトンスクリーンには主に2つのタイプがあります。

  • コンテンツプレースホルダー
  • カラープレースホルダー

コンテンツプレースホルダーは通常、FacebookとLinkedInの上の画像に示されているように、ページの外観をシミュレートする明るい灰色のボックスと円です。

カラープレースホルダーは、UIレイアウトだけでなく、ドミナントカラーもシミュレートするため、作成がより困難です。最も一般的には、PinterestやUnsplashなどの画像に焦点を当てたWebサイトで見られます。

9

Pinterestのカラープレースホルダーの例

スケルトンスクリーンを使用する理由

  • それらはより高速で、よりユーザーフレンドリーであるように見えます。知覚されるパフォーマンスの向上は、優れたUXを提供し、コンバージョン率の向上に役立ちます。
  • スピナー/ローダーの問題は、何がロードされているのか、どのくらいの時間がかかるのかわからないことです。
  • スピナー/ローダーを使用すると、ロード時間が不明になるため、ユーザーに不確実な期間が生じます。
  • スケルトン画面は、待ち時間ではなく進行状況にユーザーの注意を引き付けます。
  • それは速度と短いロード時間の幻想を作成します

いつ使用するか

  • 複数の要素が同時にロードされているときに何かがロードされていることをユーザーに通知するために使用します。
  • データの読み込みに3秒以上かかる場合に使用します。
  • トラフィックの多いWebサイトで使用します。
  • バックグラウンドまたは長時間実行されるプロセスに使用します。

心に留めておくべきこと

スケルトン画面を実装する際には、ウェブサイトやアプリで達成しようとしている目標を念頭に置き、コンテンツの読み込みを優先する必要があります。

スケルトンのロード画面を使用することは、実際のパフォーマンスの最適化をスキップする言い訳にはなりません。意味のあるコンテンツをキャッシュして表示できるのであれば、それは良いことです。

毎日の開発スケルトン読み込みUIの構築

このセクションでは、理解しやすいように、段階的なプロセスに従ってスケルトンのロード画面の実装について詳しく説明します。

daily.devのフィードセクションのようなものを作成します。

ステップ1:プロジェクトを設定する

まず、私と一緒にコーディングするには、ここでレイアウトのスターターコードを複製またはダウンロードします。DownGitを使用してファイルをダウンロードできます。

コードにはカードレイアウトが含まれているため、ここから次の手順に進みます。

まず、IDEで開発サーバーを起動し、ブラウザを開きます。

screencapture-codepen-io-israelmitolu-full-wvpOaQd-2022-04-21-17_16_47

スターターカードのレイアウト

ステップ2:スケルトン要素を設計する

スケルトンの読み込み用に作成する要素は、ロゴ画像、タイトル、詳細、カバー画像、フッターセクションの5つです。

4-3

デイリー開発者のスケルトン要素

skeleton次に、上記の要素の場所にクラスを追加します。

ロゴは、

<img class="card__header header__img skeleton" />

タイトルには、上の写真にある2本の線を表す2つのdivがあります。

<div class="skeleton skeleton-text"></div>
<div class="skeleton skeleton-text"></div>

詳細については、クラスのdiv内に次のコードを追加してくださいbody__text

<div class="skeleton skeleton-text skeleton-text__body"></div>

div内body__imgに、次のコードを追加します。

<img class="skeleton" alt="" id="cover-img" />

フッターには、次のコードを追加します。

<div class="skeleton skeleton-text skeleton-footer"></div>

これで、カードの完全なHTMLコードは次のようになります。

<a class="card" id="card-link" target="_blank">
  <div class="card__header">
    <div>
      <img class="card__header header__img skeleton" id="logo-img" alt="" />
    </div>
    <h3 class="card__header header__title" id="card-title">
      <div class="skeleton skeleton-text"></div>
      <div class="skeleton skeleton-text"></div>
    </h3>
  </div>

  <div class="card__body">
    <div class="card__body body__text" id="card-details">
      <div class="skeleton skeleton-text skeleton-text__body"></div>
    </div>

    <div class="card__body body__img">
      <img class="skeleton" alt="" id="cover-img" />
    </div>
  </div>

  <div class="card__footer" id="card-footer">
    <div class="skeleton skeleton-text skeleton-footer"></div>
  </div>
</a>

次に、スケルトンコンポーネントを作成するためのスタイルを追加しましょう。

.skeleton {
  animation: skeleton-loading 1s linear infinite alternate;
}

@keyframes skeleton-loading {
  0% {
    background-color: hsl(200, 20%, 80%);
  }
  100% {
    background-color: hsl(200, 20%, 95%);
  }
}

.skeleton-text {
  width: 100%;
  height: 0.7rem;
  margin-bottom: 0.5rem;
  border-radius: 0.25rem;
}

.skeleton-text__body {
  width: 75%;
}

.skeleton-footer {
  width: 30%;
}

結果のレイアウトは次のとおりです。

5

カードコンポーネントの読み込み

ステップ3:カードテンプレートのクローンを作成する

とファイルの要素templateの間にタグを挿入します。containercardindex.html

上の画像templateには、コメントアウトしたタグがあります。そうです、その有効なHTML要素です;)。これは、スクリプトによって複製およびドキュメントに挿入できるHTMLのフラグメントを宣言するために使用されます。

<template id="card-template">

そのため、 div</template>の終了タグの後に必ず終了タグを追加してください。card

次に、カードテンプレートのクローンを作成するために使用するJavasScriptコードを見てみましょう。

scriptタグの終わりの直前にタグを作成しbody、次のコードを追加します。

const container = document.querySelector(".container");
const cardTemplate = document.getElementById("card-template");
for (let i = 0; i < 10; i++) {
  container.append(cardTemplate.content.cloneNode(true));
}

上記のコードは、ページコンテナとカードテンプレートを取得し、カードの9つのクローン/コピーを作成します(合計で10を作成します)。次に、カードをコンテナに追加/挿入します。

6

クローンカードスケルトンUI

ステップ4:JSONファイルを作成する

ページにコンテンツを追加する前に、いくつかのデータが必要です。通常は外部のWebサイトでデータを取得する必要がありますが、このプロジェクト用に特別に設定したWebサイトを使用します。

まずdata.json、プロジェクトフォルダにというファイルを作成します。

次のコードをJSONファイルに追加します。

[
  {
    "id": 1,
    "logoImage": "https://res.cloudinary.com/daily-now/image/upload/t_logo,f_auto/v1/logos/4a287b2e7cb5499bae863f8e7137cdb4",
    "title": "Writing Cleaner CSS Using BEM ",
    "details": "Mar 12, 2022 · 4m read time",
    "coverImage": "https://res.cloudinary.com/daily-now/image/upload/f_auto,q_auto/v1/posts/dd19e7a56475f39ab1c38167c02c7b58",
    "link": "https://israelmitolu.hashnode.dev/writing-cleaner-css-using-bem-methodology"
  },
  {
    "id": 2,
    "logoImage": "https://daily-now-res.cloudinary.com/image/upload/t_logo,f_auto/v1628412854/logos/freecodecamp",
    "title": "The Beginner's Guide to Sass",
    "details": "Apr 05, 2022 · 8m read time",
    "coverImage": "https://res.cloudinary.com/daily-now/image/upload/f_auto,q_auto/v1/posts/bec6719be210973098293a32dc732d1e",
    "link": "https://www.freecodecamp.org/news/the-beginners-guide-to-sass/"
  },
  {
    "id": 3,
    "logoImage": "https://res.cloudinary.com/daily-now/image/upload/t_logo,f_auto/v1/logos/devto",
    "title": "I made Squid Game with Javascript",
    "details": "Oct 25, 2021 · 3m read time",
    "coverImage": "https://res.cloudinary.com/daily-now/image/upload/f_auto,q_auto/v1/posts/1f947033365381cbe322ddf294ad7169",
    "link": "https://dev.to/0shuvo0/i-made-squid-game-with-javascript-10j9"
  },
  {
    "id": 4,
    "logoImage": "https://res.cloudinary.com/daily-now/image/upload/t_logo,f_auto/v1/logos/4a287b2e7cb5499bae863f8e7137cdb4",
    "title": "Using Custom Cursors with Javascript for a Better User Experience",
    "details": "Feb 12, 2022 · 9m read time",
    "coverImage": "https://res.cloudinary.com/daily-now/image/upload/f_auto,q_auto/v1/posts/3d056b99c95b37cd35ae5cfc6a8b38be",
    "link": "https://israelmitolu.hashnode.dev/using-custom-cursors-with-javascript-for-a-better-user-experience"
  },
  {
    "id": 5,
    "logoImage": "https://daily-now-res.cloudinary.com/image/upload/t_logo,f_auto/v1628412854/logos/freecodecamp",
    "title": "React Best Practices - Tips for Writing Better React Code in 2022",
    "details": "Feb 03, 2022 · 31m read time",
    "coverImage": "https://res.cloudinary.com/daily-now/image/upload/f_auto,q_auto/v1/posts/5a629fff5583f9ab5f0931d14736b299",
    "link": "https://www.freecodecamp.org/news/best-practices-for-react/"
  },
  {
    "id": 6,
    "logoImage": "https://res.cloudinary.com/daily-now/image/upload/t_logo,f_auto/v1/logos/tnw",
    "title": "You suck at Googling: 5 tips to improve your search skills",
    "details": "Mar 31, 2022 · 4m read time",
    "coverImage": "https://res.cloudinary.com/daily-now/image/upload/f_auto,q_auto/v1/posts/e318150ae67c2083ff3585a96f366f7b",
    "link": "https://thenextweb.com/news/5-tips-to-improve-your-google-search-skills"
  },
  {
    "id": 7,
    "logoImage": "https://res.cloudinary.com/daily-now/image/upload/t_logo,f_auto/v1/logos/logrocket",
    "title": "A better way of solving prop drilling in React apps",
    "details": "Jan 14, 2022 · 13m read time",
    "coverImage": "https://res.cloudinary.com/daily-now/image/upload/f_auto,q_auto/v1/posts/6fe4c4060bca638b419d8b2c63d8eaf7",
    "link": "https://blog.logrocket.com/solving-prop-drilling-react-apps/"
  },
  {
    "id": 8,
    "logoImage": "https://res.cloudinary.com/daily-now/image/upload/t_logo,f_auto/v1/logos/dz",
    "title": "Golang and Event-Driven Architecture",
    "details": "Apr 18, 2022 · 6m read time",
    "coverImage": "https://res.cloudinary.com/daily-now/image/upload/f_auto,q_auto/v1/posts/d06eddd82c62288df6e2600bcda61579",
    "link": "https://dzone.com/articles/golang-and-event-driven-architecture"
  },
  {
    "id": 9,
    "logoImage": "https://res.cloudinary.com/daily-now/image/upload/t_logo,f_auto/v1/logos/4a287b2e7cb5499bae863f8e7137cdb4",
    "title": "Introduction to Git In 16 Minutes",
    "details": "Mar 18, 2021 · 8m read time",
    "coverImage": "https://res.cloudinary.com/daily-now/image/upload/f_auto,q_auto/v1/posts/3c02111a8f242f607551500432e17a78",
    "link": "https://vickyikechukwu.hashnode.dev/introduction-to-git-in-16-minutes"
  },
  {
    "id": 10,
    "logoImage": "https://res.cloudinary.com/daily-now/image/upload/t_logo,f_auto/v1/logos/4a287b2e7cb5499bae863f8e7137cdb4",
    "title": "How to Create a Sleek Preloader Animation Using GSAP Timeline",
    "details": "Jan 25, 2022 · 7m read time",
    "coverImage": "https://res.cloudinary.com/daily-now/image/upload/f_auto,q_auto/v1/posts/e238c35cb9d41dd9a5475602aef00119",
    "link": "https://israelmitolu.hashnode.dev/how-to-create-a-sleek-preloader-animation-using-gsap-timeline"
  }
]

Daily Devのフィードセクションを複製するために、ID、ロゴ画像、タイトル、詳細、カバー画像などのプロパティを持つオブジェクトの配列を持つデータを作成しました。

ステップ5:HTML要素に適切なコンテンツを入力する

JavaScriptを格納するスクリプトタグに次のコードを追加します。

fetch("data.json")
  .then((response) => response.json())
  .then((posts) => {
    container.innerHTML = "";
    posts.forEach((post) => {
      const div = cardTemplate.content.cloneNode(true);
      div.getElementById("card-link").href = post.link;
      div.getElementById("logo-img").src = post.logoImage;
      div.getElementById("card-title").textContent = post.title;
      div.getElementById("card-details").textContent = post.details;
      div.getElementById("cover-img").src = post.coverImage;
      div.getElementById(
        "card-footer"
      ).innerHTML = ` <ion-icon name="arrow-up"></ion-icon>
          <ion-icon name="chatbox-ellipses"></ion-icon>
          <ion-icon name="bookmark"></ion-icon>`;
      container.append(div);
    });
  });

上記のコードは、カードの読み込みが完了したら、カードにコンテンツを追加するために使用するものです。

それでは、コードを少しずつ説明しましょう。

fetch("data.json")
  .then((response) => response.json())

ここに、リソースへのパスを設定する基本的なフェッチ要求があります。この場合、data.jsonファイル。外部APIの場合は、エンドポイントURLを引数として使用します。

このfetch()メソッドは、JSON応答本文を直接返すのではなく、Responseオブジェクトで解決されるpromiseを返します。

詳細については、 MDNドキュメントをご覧ください。

.then((posts) => {
    container.innerHTML = "";
    posts.forEach((post) => {
      const div = cardTemplate.content.cloneNode(true);
      div.getElementById("logo-img").src = post.logoImage;
      div.getElementById("card-title").textContent = post.title;
      div.getElementById("card-details").textContent = post.details;
      div.getElementById("cover-img").src = post.coverImage;
      div.getElementById(
        "card-footer"
      ).innerHTML = `<ion-icon name="arrow-up"></ion-icon>
          <ion-icon name="chatbox-ellipses"></ion-icon>
          <ion-icon name="bookmark"></ion-icon>`;
      container.append(div);
    });
  });

ここでは、データをフェッチした後に何が起こるかを定義します。

コードは最初にページをクリアし、次にforEach()JSONファイルからプロパティを抽出するメソッドを実行し、プロパティを使用してカード要素(ロゴ画像、カードタイトルなど)に入力し.textContentます。

最後に、フッターでは.innerHTML、アイコンをHTMLコンテンツとして挿入していました。

すべてを正しく追加した場合、エラーは発生しないはずです。これは、完全に機能するスケルトン読み込みUIです。

7-1

完成したDailyDevスケルトンUI

Githubのライブデモソースコードリポジトリを確認してください。

ChromeDevToolsでのネットワークスロットリング

このスケルトン画面はユーザーのネットワーク速度に依存するため、タイムアウトを設定しなかったことに注意することが重要です。

さまざまなネットワーク速度でシミュレートする場合は、ブラウザのDevtoolsの[ネットワーク]タブに移動します。

Chromev100でそれを行う方法は次のとおりです。

8

ChromeDevToolsのスロットルネットワーク

  1. DevToolsを開きます(Ctrl + Shift + i)。
  2. [ネットワーク]タブに移動します。
  3. 必要な接続のタイプを選択します
  4. ページをリロードして、指定した接続速度でアセットがダウンロードされていることを確認します。

デフォルトのオプションが適切でない場合は、ドロップダウンメニューの最上部にあるオプションを選択して、カスタムのネットワークスロットリングプロファイルを作成できます。

結論

あなたは最後までそれを成し遂げました!スケルトンの読み込みと、データを読み込むときに速度の錯覚を作成することでユーザーエクスペリエンスにどのように貢献するかを学び、独自の実装を行いました。

このチュートリアルがお役に立てば幸いです。また、さまざまなスケルトンロード画面を作成するための良い出発点として役立つことを願っています。

この記事が洞察に満ちていると感じた場合は、友達やネットワークと共有してください。また、 Twitterブログで私と連絡を取り、より良い開発者になるためのリソースや記事を共有してください。

読んでくれてありがとう、そして幸せなコーディング!

先に進む前に、ReactAngularVueのスケルトンロードパッケージをいくつか紹介します。

ソース:https ://www.freecodecamp.org/news/how-to-build-skeleton-screens-using-css-for-better-user-experience/

 #css #react #angular #vue #skeleton

より良いUXのためにCSSでスケルトンスクリーンを構築する

Cómo Construir Una Pantalla De Esqueleto Con CSS Para Una Mejor UX

Cargadores de contenido, pantallas esqueléticas, elementos fantasma y marcadores de posición de contenido. Estos son los nombres dados al efecto que exploraremos hoy.

Muchas empresas, como Linkedin, Facebook, Youtube y Slack, utilizan este efecto en sus aplicaciones y sitios web, como habrás notado.

Por mucho que los desarrolladores queramos que nuestros sitios web se carguen lo más rápido posible, hay momentos en los que es necesario representar una gran cantidad de datos en la página, por lo que las pantallas Skeleton son una excelente opción.

requisitos previos

Este artículo asume que usted tiene:

  • Conocimientos de HTML y CSS (SASS)
  • Conocimiento de JavaScript (ES6)

Usaremos HTML y SASS para este proyecto. Si desea comenzar con SASS, consulte esta Guía para principiantes.

¿Qué es una pantalla de esqueleto?

Una pantalla esqueleto es un marcador de posición animado que simula el diseño de un sitio web mientras se cargan los datos.

Le informan al usuario que se está cargando algún contenido y, lo que es más importante, brindan una indicación de lo que se está cargando, ya sea una imagen, texto, tarjeta, etc.

Esto le da al usuario la impresión de que el sitio web es más rápido porque ya sabe qué tipo de contenido se está cargando antes de que aparezca. Esto se conoce como rendimiento percibido .

Estos son algunos ejemplos de pantallas esqueléticas de Facebook y LinkedIn:

1-2

Estado de carga del feed de inicio de LinkedIn

2-2

Estado de carga del feed de inicio de Facebook

Diferentes tipos de pantallas de esqueleto

Hay 2 tipos principales de pantallas de esqueleto:

  • Marcadores de posición de contenido
  • Marcadores de posición de color

Los marcadores de posición de contenido suelen ser cuadros y círculos de color gris claro que simulan la apariencia de la página, como se muestra en las imágenes de arriba para Facebook y LinkedIn.

Los marcadores de posición de color son más difíciles de crear porque simulan no solo el diseño de la interfaz de usuario, sino también el color dominante. Se encuentra más comúnmente en sitios web enfocados en imágenes como Pinterest y Unsplash.

9

Ejemplo de marcador de posición de color de Pinterest

¿Por qué usar pantallas de esqueleto?

  • Parecen ser más rápidos y más fáciles de usar. El rendimiento percibido mejorado proporciona una buena experiencia de usuario y ayuda a aumentar la tasa de conversión.
  • El problema con los giradores/cargadores es que no tenemos idea de qué se está cargando o cuánto tiempo llevará.
  • El uso de spinners/cargadores crea un período de incertidumbre para el usuario ya que se desconoce el tiempo de carga.
  • Las pantallas esqueléticas llaman la atención del usuario sobre el progreso en lugar del tiempo de espera.
  • Crea una ilusión de velocidad y tiempo de carga corto.

Cuándo usarlos

  • Úselo para notificar al usuario que algo se está cargando cuando más de un elemento se está cargando al mismo tiempo.
  • Utilícelo cuando la carga de datos tarde más de 3 segundos.
  • Uso en sitios web con mucho tráfico.
  • Úselo para un proceso en segundo plano o de larga ejecución.

Cosas a tener en cuenta

Al implementar pantallas de esqueleto, debemos tener en cuenta el objetivo que intentamos lograr con el sitio web o la aplicación, y priorizar la carga del contenido.

El uso de pantallas de carga esqueléticas no es excusa para omitir la optimización del rendimiento real, y si puede almacenar en caché contenido significativo y mostrarlo, será bueno.

Creación de una interfaz de usuario de carga de esqueleto de desarrollo diario

En esta sección, profundizaremos en la implementación de la pantalla de carga básica siguiendo un proceso paso a paso para que sea más fácil de entender.

Construiremos uno como la sección de noticias de daily.dev.

Paso 1: configurar el proyecto

Primero, para codificar conmigo, clone o descargue el código de inicio para el diseño aquí . Puede descargar los archivos utilizando DownGit .

El código contiene el diseño de la tarjeta, por lo que continuaremos desde aquí en los próximos pasos.

Para comenzar, inicie el servidor de desarrollo en el IDE y abra su navegador.

captura de pantalla-codepen-io-israelmitolu-full-wvpOaQd-2022-04-21-17_16_47

Diseño de la tarjeta de inicio

Paso 2: Diseña los elementos del Esqueleto

Hay 5 elementos que queremos construir para la carga del esqueleto: la imagen del logotipo, el título, los detalles, la imagen de portada y la sección de pie de página.

4-3

Elementos esqueléticos de Daily Dev

Ahora, agregaremos skeletonclases a las ubicaciones de los elementos anteriores.

Para el logotipo,

<img class="card__header header__img skeleton" />

Para el título, habrá 2 divs para representar las dos líneas que tenemos en la imagen de arriba.

<div class="skeleton skeleton-text"></div>
<div class="skeleton skeleton-text"></div>

Para obtener más información, agregue el siguiente código dentro del div de la clase body__text:

<div class="skeleton skeleton-text skeleton-text__body"></div>

Dentro del body__imgdiv, agregue el siguiente código:

<img class="skeleton" alt="" id="cover-img" />

Para el pie de página, agregue este código:

<div class="skeleton skeleton-text skeleton-footer"></div>

Ahora, el código HTML completo de la tarjeta:

<a class="card" id="card-link" target="_blank">
  <div class="card__header">
    <div>
      <img class="card__header header__img skeleton" id="logo-img" alt="" />
    </div>
    <h3 class="card__header header__title" id="card-title">
      <div class="skeleton skeleton-text"></div>
      <div class="skeleton skeleton-text"></div>
    </h3>
  </div>

  <div class="card__body">
    <div class="card__body body__text" id="card-details">
      <div class="skeleton skeleton-text skeleton-text__body"></div>
    </div>

    <div class="card__body body__img">
      <img class="skeleton" alt="" id="cover-img" />
    </div>
  </div>

  <div class="card__footer" id="card-footer">
    <div class="skeleton skeleton-text skeleton-footer"></div>
  </div>
</a>

Ahora, agreguemos algo de estilo para hacer los componentes del esqueleto:

.skeleton {
  animation: skeleton-loading 1s linear infinite alternate;
}

@keyframes skeleton-loading {
  0% {
    background-color: hsl(200, 20%, 80%);
  }
  100% {
    background-color: hsl(200, 20%, 95%);
  }
}

.skeleton-text {
  width: 100%;
  height: 0.7rem;
  margin-bottom: 0.5rem;
  border-radius: 0.25rem;
}

.skeleton-text__body {
  width: 75%;
}

.skeleton-footer {
  width: 30%;
}

Este es el diseño resultante:

5

Carga de componentes de la tarjeta

Paso 3: Clona la plantilla de la tarjeta

Inserte una templateetiqueta entre containery el cardelemento en el index.htmlarchivo.

En la imagen de arriba hay una templateetiqueta que comenté, y sí, es un elemento HTML válido ;). Se utiliza para declarar fragmentos de HTML que se pueden clonar e insertar en el documento mediante script.

<template id="card-template">

Como resultado, asegúrese de agregar la etiqueta de cierre </template>después de la etiqueta de cierre del carddiv.

Ahora veamos el código JavasScript que usaremos para clonar la plantilla de la tarjeta.

Cree una scriptetiqueta justo antes del final de la bodyetiqueta y agregue el siguiente código:

const container = document.querySelector(".container");
const cardTemplate = document.getElementById("card-template");
for (let i = 0; i < 10; i++) {
  container.append(cardTemplate.content.cloneNode(true));
}

El código anterior toma el contenedor de la página y la plantilla de la tarjeta, y luego crea 9 clones/copias de la tarjeta (haciendo 10 en total). Luego agrega/inserta las tarjetas en el contenedor.

6

Interfaz de usuario de esqueleto de tarjeta clonada

Paso 4: Crea un archivo JSON

Necesitamos algunos datos antes de que podamos agregar contenido a la página. Normalmente, necesitaría obtener datos con un sitio web externo, pero usaremos uno que configuré específicamente para este proyecto.

Para comenzar, cree un archivo llamado data.jsonen la carpeta del proyecto.

Agregue el siguiente código al archivo JSON.

[
  {
    "id": 1,
    "logoImage": "https://res.cloudinary.com/daily-now/image/upload/t_logo,f_auto/v1/logos/4a287b2e7cb5499bae863f8e7137cdb4",
    "title": "Writing Cleaner CSS Using BEM ",
    "details": "Mar 12, 2022 · 4m read time",
    "coverImage": "https://res.cloudinary.com/daily-now/image/upload/f_auto,q_auto/v1/posts/dd19e7a56475f39ab1c38167c02c7b58",
    "link": "https://israelmitolu.hashnode.dev/writing-cleaner-css-using-bem-methodology"
  },
  {
    "id": 2,
    "logoImage": "https://daily-now-res.cloudinary.com/image/upload/t_logo,f_auto/v1628412854/logos/freecodecamp",
    "title": "The Beginner's Guide to Sass",
    "details": "Apr 05, 2022 · 8m read time",
    "coverImage": "https://res.cloudinary.com/daily-now/image/upload/f_auto,q_auto/v1/posts/bec6719be210973098293a32dc732d1e",
    "link": "https://www.freecodecamp.org/news/the-beginners-guide-to-sass/"
  },
  {
    "id": 3,
    "logoImage": "https://res.cloudinary.com/daily-now/image/upload/t_logo,f_auto/v1/logos/devto",
    "title": "I made Squid Game with Javascript",
    "details": "Oct 25, 2021 · 3m read time",
    "coverImage": "https://res.cloudinary.com/daily-now/image/upload/f_auto,q_auto/v1/posts/1f947033365381cbe322ddf294ad7169",
    "link": "https://dev.to/0shuvo0/i-made-squid-game-with-javascript-10j9"
  },
  {
    "id": 4,
    "logoImage": "https://res.cloudinary.com/daily-now/image/upload/t_logo,f_auto/v1/logos/4a287b2e7cb5499bae863f8e7137cdb4",
    "title": "Using Custom Cursors with Javascript for a Better User Experience",
    "details": "Feb 12, 2022 · 9m read time",
    "coverImage": "https://res.cloudinary.com/daily-now/image/upload/f_auto,q_auto/v1/posts/3d056b99c95b37cd35ae5cfc6a8b38be",
    "link": "https://israelmitolu.hashnode.dev/using-custom-cursors-with-javascript-for-a-better-user-experience"
  },
  {
    "id": 5,
    "logoImage": "https://daily-now-res.cloudinary.com/image/upload/t_logo,f_auto/v1628412854/logos/freecodecamp",
    "title": "React Best Practices - Tips for Writing Better React Code in 2022",
    "details": "Feb 03, 2022 · 31m read time",
    "coverImage": "https://res.cloudinary.com/daily-now/image/upload/f_auto,q_auto/v1/posts/5a629fff5583f9ab5f0931d14736b299",
    "link": "https://www.freecodecamp.org/news/best-practices-for-react/"
  },
  {
    "id": 6,
    "logoImage": "https://res.cloudinary.com/daily-now/image/upload/t_logo,f_auto/v1/logos/tnw",
    "title": "You suck at Googling: 5 tips to improve your search skills",
    "details": "Mar 31, 2022 · 4m read time",
    "coverImage": "https://res.cloudinary.com/daily-now/image/upload/f_auto,q_auto/v1/posts/e318150ae67c2083ff3585a96f366f7b",
    "link": "https://thenextweb.com/news/5-tips-to-improve-your-google-search-skills"
  },
  {
    "id": 7,
    "logoImage": "https://res.cloudinary.com/daily-now/image/upload/t_logo,f_auto/v1/logos/logrocket",
    "title": "A better way of solving prop drilling in React apps",
    "details": "Jan 14, 2022 · 13m read time",
    "coverImage": "https://res.cloudinary.com/daily-now/image/upload/f_auto,q_auto/v1/posts/6fe4c4060bca638b419d8b2c63d8eaf7",
    "link": "https://blog.logrocket.com/solving-prop-drilling-react-apps/"
  },
  {
    "id": 8,
    "logoImage": "https://res.cloudinary.com/daily-now/image/upload/t_logo,f_auto/v1/logos/dz",
    "title": "Golang and Event-Driven Architecture",
    "details": "Apr 18, 2022 · 6m read time",
    "coverImage": "https://res.cloudinary.com/daily-now/image/upload/f_auto,q_auto/v1/posts/d06eddd82c62288df6e2600bcda61579",
    "link": "https://dzone.com/articles/golang-and-event-driven-architecture"
  },
  {
    "id": 9,
    "logoImage": "https://res.cloudinary.com/daily-now/image/upload/t_logo,f_auto/v1/logos/4a287b2e7cb5499bae863f8e7137cdb4",
    "title": "Introduction to Git In 16 Minutes",
    "details": "Mar 18, 2021 · 8m read time",
    "coverImage": "https://res.cloudinary.com/daily-now/image/upload/f_auto,q_auto/v1/posts/3c02111a8f242f607551500432e17a78",
    "link": "https://vickyikechukwu.hashnode.dev/introduction-to-git-in-16-minutes"
  },
  {
    "id": 10,
    "logoImage": "https://res.cloudinary.com/daily-now/image/upload/t_logo,f_auto/v1/logos/4a287b2e7cb5499bae863f8e7137cdb4",
    "title": "How to Create a Sleek Preloader Animation Using GSAP Timeline",
    "details": "Jan 25, 2022 · 7m read time",
    "coverImage": "https://res.cloudinary.com/daily-now/image/upload/f_auto,q_auto/v1/posts/e238c35cb9d41dd9a5475602aef00119",
    "link": "https://israelmitolu.hashnode.dev/how-to-create-a-sleek-preloader-animation-using-gsap-timeline"
  }
]

Para replicar la sección de noticias de Daily Dev, hemos creado algunos datos que tienen una matriz de objetos con propiedades como identificación, imagen de logotipo, título, detalles e imagen de portada.

Paso 5: rellene los elementos HTML con el contenido adecuado

Agrega el siguiente código a la etiqueta del script que aloja tu JavaScript:

fetch("data.json")
  .then((response) => response.json())
  .then((posts) => {
    container.innerHTML = "";
    posts.forEach((post) => {
      const div = cardTemplate.content.cloneNode(true);
      div.getElementById("card-link").href = post.link;
      div.getElementById("logo-img").src = post.logoImage;
      div.getElementById("card-title").textContent = post.title;
      div.getElementById("card-details").textContent = post.details;
      div.getElementById("cover-img").src = post.coverImage;
      div.getElementById(
        "card-footer"
      ).innerHTML = ` <ion-icon name="arrow-up"></ion-icon>
          <ion-icon name="chatbox-ellipses"></ion-icon>
          <ion-icon name="bookmark"></ion-icon>`;
      container.append(div);
    });
  });

El código anterior es lo que usaremos para agregar contenido a las tarjetas una vez que terminen de cargarse.

Ahora, déjame explicarte el código poco a poco:

fetch("data.json")
  .then((response) => response.json())

Aquí, tenemos una solicitud de recuperación básica, donde establecemos la ruta al recurso. En este caso, el data.jsonarchivo. Si fuera una API externa, usaría la URL del punto final como argumento:

El fetch()método no devuelve directamente el cuerpo de la respuesta JSON, sino una promesa que se resuelve con un objeto de respuesta.

Para obtener más información, consulta los documentos de MDN .

.then((posts) => {
    container.innerHTML = "";
    posts.forEach((post) => {
      const div = cardTemplate.content.cloneNode(true);
      div.getElementById("logo-img").src = post.logoImage;
      div.getElementById("card-title").textContent = post.title;
      div.getElementById("card-details").textContent = post.details;
      div.getElementById("cover-img").src = post.coverImage;
      div.getElementById(
        "card-footer"
      ).innerHTML = `<ion-icon name="arrow-up"></ion-icon>
          <ion-icon name="chatbox-ellipses"></ion-icon>
          <ion-icon name="bookmark"></ion-icon>`;
      container.append(div);
    });
  });

Aquí, definimos lo que debería suceder después de obtener los datos.

El código primero borra la página y luego ejecuta un forEach()método que extrae las propiedades del archivo JSON y luego lo ingresa en los elementos de la tarjeta (imagen del logotipo, título de la tarjeta,...) usando .textContentla propiedad.

Finalmente, para el pie de página, solíamos .innerHTMLinsertar los íconos como contenido HTML.

Si agregó todo correctamente, no debería haber ningún error, y esta es nuestra interfaz de usuario de carga de esqueleto completamente funcional.

7-1

Nuestra interfaz de usuario de esqueleto de Daily Dev terminada

Consulte la demostración en vivo y el repositorio de código fuente en Github.

Limitación de red en Chrome DevTools

Es importante tener en cuenta que no establecimos un tiempo de espera porque esta pantalla básica depende de la velocidad de la red del usuario.

Si desea simularlo a diferentes velocidades de red, vaya a la pestaña de red en Devtools de su navegador.

He aquí cómo hacerlo en Chrome v100:

8

Acelerador de red en Chrome DevTools

  1. Abra DevTools (Ctrl+Mayús+i).
  2. Vaya a la pestaña "Red".
  3. Seleccione el tipo de conexión que desea
  4. Vuelva a cargar la página para ver los activos que se descargan a la velocidad de conexión especificada.

Si las opciones predeterminadas no le convienen, puede crear un perfil de limitación de red personalizado seleccionando la opción en la parte superior del menú desplegable.

Conclusión

¡Llegaste hasta el final! Aprendió sobre la carga de esqueleto y cómo contribuye a la experiencia del usuario al crear la ilusión de velocidad al cargar datos, y ha implementado la suya propia.

Espero que hayas encontrado útil este tutorial y que sirva como un buen punto de partida para crear varias pantallas de carga de esqueleto.

Si encontró este artículo revelador, compártalo con sus amigos y su red. Además, no dude en conectarse conmigo en Twitter y mi blog donde comparto recursos y artículos para que sea un mejor desarrollador.

¡Gracias por leer y feliz codificación!

Antes de ir, aquí hay algunos paquetes de carga de esqueleto para React , Angular y Vue .

Fuente: https://www.freecodecamp.org/news/how-to-build-skeleton-screens-using-css-for-better-user-experience/ 

#css #react #angular #vue #skeleton 

Cómo Construir Una Pantalla De Esqueleto Con CSS Para Una Mejor UX
Effie  Predovic

Effie Predovic

1627287240

Implement Skeleton Loader with React using API

In this video, we are going to implement skeleton loader in React application with the help of Ant design and 3rd party fake api.

#react #api #skeleton

Implement Skeleton Loader with React using API
Willis  Mills

Willis Mills

1625068740

Skeleton UI Tutorial | React Native Animated

Learn how to create the skeleton ui animation using the react native animated api.

New To React Native?
React Native Foundation + Firebase + Redux :
https://www.udemy.com/course/react-native-foundation/?referralCode=687495CA6B80FFD08B88

Was it helpful?
Support : https://www.buymeacoffee.com/unsureprogammer

Twitter https://twitter.com/nathvarun
Instagram https://www.instagram.com/nathvarun25
Facebook https://www.facebook.com/nathvarun
Contact unsureprogrammer@gmail.com

#react native #react native animated #skeleton #ui #tutorial #firebase

Skeleton UI Tutorial | React Native Animated
Willis  Mills

Willis Mills

1625065020

Skeleton UI Reanimated | React Native Animations

Starter Project : https://github.com/nathvarun/skeleton-ui-react-native-animated/tree/master

Learn how to create the skeleton ui animation using the react-native-reanimated api.

New To React Native?
React Native Foundation + Firebase + Redux :
https://www.udemy.com/course/react-native-foundation/?referralCode=687495CA6B80FFD08B88

Was it helpful?
Support : https://www.buymeacoffee.com/unsureprogammer

Twitter https://twitter.com/nathvarun
Instagram https://www.instagram.com/nathvarun25
Facebook https://www.facebook.com/nathvarun
Contact unsureprogrammer@gmail.com

#react native #skeleton #react native animations

Skeleton UI Reanimated | React Native Animations

Skeleton Loader: An overview, purpose, usage and design

In this era of digitalization, teams are focusing more on giving best experience to the users. So, user experience keeps on evolving, new methodologies and components are being adopted by the teams. One among them is Skeleton Loader which you might have seen on many web sites and mobile apps.

While building a product, we always try to ensure great performance from an API turnaround time, design and rendering point of view. But, no matter how hard we try there will always be a point where user has to wait. To provide best experience during this waiting is of utmost importance in evaluating the performance of the whole product. You must have seen different kinds of loaders on various websites, viz., spinner, progress bar, loading message etc.

Skeleton Loader is of same kind and to keep users involved in the process.

In this article, we will learn about Skeleton loader, its purpose, usage, and points to keep in mind while designing. Also, we will go through the practical implementation later.

#html-css #skeleton #css #c #c++

Skeleton Loader: An overview, purpose, usage and design