備忘録

備忘録

HandsontableをReactで利用する方法

Ⅰ. はじめに

タイトルの通り「HandsontableをReactで利用する方法」です

Ⅱ. 手順

1. 必要なパッケージをインストールする
npm install handsontable @handsontable/react
2. サンプルプログラムを書く
import { registerAllModules } from 'handsontable/registry'
import { HotTable } from '@handsontable/react'

import 'handsontable/dist/handsontable.full.min.css'

registerAllModules()

export default function App(): JSX.Element {
  return (
    <HotTable
      data={[
        ['id', 'name', 'age', 'gender'],
        [1, 'tanaka', 11, 'm'],
        [2, 'yamada', 12, 'f'],
        [3, 'takahashi', 15, 'm']
      ]}
      rowHeaders={true}
      colHeaders={true}
      height="auto"
      autoWrapRow={true}
      autoWrapCol={true}
      licenseKey="non-commercial-and-evaluation"
    />
  )
}

実行結果

ReactでGoogleMAP利用する方法

Ⅰ. はじめに

タイトルの通り「ReactでGoogleMAP利用する方法」です。

Ⅱ. 手順

1. Google MAP PlatformのAPIキーを生成する

https://console.cloud.google.com/google/maps-apis/credentials

2. 必要なライブラリをインストールする
npm install @googlemaps/js-api-loader
npm install @types/google.maps
3. サンプルプログラムを書く
import { Loader } from '@googlemaps/js-api-loader'
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';

const GoogleMapApiKey = 'YOUR_GOOGLE_MAP_API_KEY'
const GoogleMapPosition: google.maps.LatLngLiteral = { lat: 35.6812362, lng: 139.7645499 } // 東京駅

export default function App(): JSX.Element {
  const mapRef = useRef<HTMLDivElement>(null)

  const [mapsLibrary, setMapsLibrary] = useState<google.maps.MapsLibrary>()
  const [markerLibrary, setMarkerLibrary] = useState<google.maps.MarkerLibrary>()
  const [geocodingLibrary, setGeocodingLibrary] = useState<google.maps.GeocodingLibrary>()
  const [map, setMap] = useState<google.maps.Map>()
  const [address, setAddress] = useState<string>('')
  const [markers, setMarkers] = useState<google.maps.marker.AdvancedMarkerElement[]>([])

  const loader = useMemo(() => new Loader({
    apiKey: GoogleMapApiKey,
    version: '3',
    libraries:['maps']
  }), [])

  /**
   * マーカーを追加する
   */
  const addMarker = useCallback((position: google.maps.LatLngLiteral | google.maps.LatLng, title: string): void => {
    if (!markerLibrary) {
      console.log('markerLibrary is null')
      return
    }

    const marker = new markerLibrary.AdvancedMarkerElement({
      map: map,
      position: position,
      title: title
    })

    setMarkers((markers) => [...markers, marker])
  }, [map, markerLibrary])

  /**
   * マーカーを全て削除する
   */
  function clearAllMarker(): void {
    for (const marker of markers) {
      marker.map = null
    }
  }

  useEffect(() => {
    async function asyncFunction() {
      const mapsLibrary = await loader.importLibrary('maps')
      const markerLibrary = await loader.importLibrary('marker')
      const geocodingLibrary = await loader.importLibrary('geocoding')
      setMapsLibrary(mapsLibrary)
      setMarkerLibrary(markerLibrary)
      setGeocodingLibrary(geocodingLibrary)
    }

    asyncFunction()
  }, [loader])

  useEffect(() => {
    if (!mapsLibrary) {
      return
    }

    // Google Mapを描画する
    const map = new mapsLibrary.Map(mapRef.current!, {
      center: GoogleMapPosition,
      zoom: 6,
      mapId: 'DEMO_MAP_ID'
    })
    setMap(map)
  }, [mapsLibrary])

  useEffect(() => {
    if (!markerLibrary) {
      return
    }

    // マーカーを描画する
    addMarker(GoogleMapPosition, 'Title001')
  }, [markerLibrary, addMarker])

  async function onFormSubmit(e: React.FormEvent<HTMLFormElement>): Promise<void> {
    e.preventDefault()

    if (!geocodingLibrary) {
      return
    }

    const request: google.maps.GeocoderRequest = {
      address: address
    }
    const result = await new geocodingLibrary.Geocoder().geocode(request)
    if (result.results.length > 0) {
      if (!map) {
        return
      }

      const location = result.results[0].geometry.location

      // 地図の中心座標を変更する
      map.setCenter(location)

      // マーカーを描画する
      addMarker(location, address)
    }
  }

  return (
    <>
      <form onSubmit={(e) => onFormSubmit(e)}>
        <label htmlFor="address">住所</label>
        <input type="text" id="address" value={address} onChange={(e) => setAddress(e.target.value)} />
        <button type="submit">送信</button>
      </form>

      <div>
        <button onClick={() => clearAllMarker()}>マーカー全削除</button>
      </div>

      <div ref={mapRef} style={{ width: '500px', height: '500px' }}></div>
    </>
  )
}

実行結果


Fabric.jsを利用してWebサイトに画像編集機能を実装する方法

Ⅰ. はじめに

タイトルの通り「Fabric.jsを利用してWebサイトに画像編集機能を実装する方法」です

Ⅱ. サンプルプログラム

<html>
  <style>
    canvas {
      border: 1px black solid;
    }
  </style>

  <body>
    <canvas id="canvas001" width="300" height="300"></canvas>
    <button onclick="downloadImage()">Download</button>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/5.3.1/fabric.min.js" referrerpolicy="no-referrer"></script>

    <script>
      const canvas = new fabric.Canvas('canvas001')

      // 100x100 の正方形を追加する
      const rect = new fabric.Rect({
        top: 100,
        left: 100,
        width: 100,
        height: 100,
        fill: '#20b2aa',
      })
      canvas.add(rect)

      // 画像を追加する
      fabric.Image.fromURL('https://files.catbox.moe/q5frwn.png', (img) => {
        img
        .set({ left: 50, top: 50})
        .scale(0.1)
        .set('flipY', true)
        canvas.add(img)
      }, {
        crossOrigin: "Anonymous" // "out.png" を保存する時にエラーが出るのを回避する
      })

      function downloadImage() {
        const aElement = document.createElement('a')
        aElement.download = 'out.png'
        aElement.href = canvas.toDataURL('image/png')
        aElement.click()
        aElement.remove()
      }
    </script>
  </body>
</html>

実行結果


Dapperで複数テーブルをクラスにマップする方法

Ⅰ. はじめに

タイトルの通り「Dapperで複数テーブルをクラスにマップする方法」です。

Ⅱ. サンプルテーブル定義

usersテーブル

id name
1 user001
2 user002
3 user003

tagsテーブル

id user_id name
1 1 tag001
2 2 tag002

Ⅲ. サンプルプログラム

Program.cs

using Dapper;
using MySqlConnector;

var connectionString = "userid=YOUR_USER;password=YOUR_PASS;database=YOUR_DB;Host=YOUR_HOST";

using var conn = new MySqlConnection(connectionString);
conn.Open();

var parameters = new DynamicParameters();

var sql = """
  select
    u.*,
    t.*
  from users u
  left outer join tags t on u.id = t.user_id
  """;

var userInfos = conn.Query<User, Tag?, UserInfo>(
  sql,
  (user, tag) => new UserInfo
  {
    UserId = user.Id,
    UserName = user.Name,
    TagName = tag?.Name
  },
  parameters,
  splitOn: "id")
  .ToArray();

foreach (var x in userInfos)
{
  Console.WriteLine($"{x.UserId}, {x.UserName}, {x.TagName}");
}

class User
{
  public required uint Id { get; set; }
  public required string Name { get; set; }
}

class Tag
{
  public required uint Id { get; set; }
  public required uint UserId { get; set; }
  public required string Name { get; set; }
}

class UserInfo
{
  public required uint UserId { get; set; }
  public required string UserName { get; set; }
  public required string? TagName { get; set; }
}

実行結果

1, user001, tag001
2, user002, tag002
3, user003,

Node.jsでxlsxファイルを生成する方法

Ⅰ. はじめに

タイトルの通り「Node.jsでxlsxファイルを生成する方法」です。

Ⅱ. 手順

1. 必要なパッケージをインストールする
npm install https://cdn.sheetjs.com/xlsx-0.20.2/xlsx-0.20.2.tgz
npm install --save-dev @types/node
2. サンプルプログラムを書く
import * as fs from 'fs'
import * as xlsx from 'xlsx'

// ワークブックを新規作成する
const workBook = xlsx.utils.book_new()

// ワークシートを新規作成する
const workSheet = xlsx.utils.aoa_to_sheet([
  ['Name', 'Age'],
  ['user001', 10],
  ['user002', 20],
  ['user003', 30],
])

// ワークブックにワークシートを追加する
xlsx.utils.book_append_sheet(workBook, workSheet, 'test001')

// out.xlsx を作成する
// xlsx.set_fs(fs)
// xlsx.writeFile(workBook, 'out.xlsx')

// out.xlsx を作成する
const bytes = xlsx.write(workBook, { bookType: 'xlsx', type: 'buffer' })
fs.writeFileSync('out.xlsx', bytes)

実行結果